@@ -42,20 +42,22 @@ private fun Array<Any?>.replaceEntryWithNode(keyIndex: Int, nodeIndex: Int, newN
42
42
return newBuffer
43
43
}
44
44
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
+
45
54
private fun Array<Any?>.removeEntryAtIndex (keyIndex : Int ): Array <Any ?> {
46
55
val newBuffer = arrayOfNulls<Any ?>(this .size - ENTRY_SIZE )
47
56
this .copyInto(newBuffer, endIndex = keyIndex)
48
57
this .copyInto(newBuffer, keyIndex, startIndex = keyIndex + ENTRY_SIZE , endIndex = this .size)
49
58
return newBuffer
50
59
}
51
60
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
-
59
61
60
62
61
63
internal class TrieNode <K , V >(
@@ -170,17 +172,38 @@ internal class TrieNode<K, V>(
170
172
return TrieNode (dataMap, nodeMap, newBuffer, mutator.ownership)
171
173
}
172
174
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 > {
174
176
// assert(buffer[nodeIndex] !== newNode)
177
+ val newNodeBuffer = newNode.buffer
178
+ if (newNodeBuffer.size == 2 && newNode.nodeMap == 0 ) {
179
+ val keyIndex = entryKeyIndex(positionMask)
180
+ val newBuffer = buffer.replaceNodeWithEntry(nodeIndex, keyIndex, newNodeBuffer[0 ], newNodeBuffer[1 ])
181
+ return TrieNode (dataMap xor positionMask, nodeMap xor positionMask, newBuffer)
182
+ }
175
183
176
- val newBuffer = buffer.copyOf()
184
+ val newBuffer = buffer.copyOf(buffer.size )
177
185
newBuffer[nodeIndex] = newNode
178
186
return TrieNode (dataMap, nodeMap, newBuffer)
179
187
}
180
188
181
- private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <K , V >, owner : MutabilityOwnership ): TrieNode <K , V > {
189
+ private fun mutableUpdateNodeAtIndex (nodeIndex : Int , positionMask : Int , newNode : TrieNode <K , V >, owner : MutabilityOwnership ): TrieNode <K , V > {
182
190
// assert(buffer[nodeIndex] !== newNode)
183
191
192
+ val newNodeBuffer = newNode.buffer
193
+ if (newNodeBuffer.size == 2 && newNode.nodeMap == 0 ) {
194
+ val keyIndex = entryKeyIndex(positionMask)
195
+ val newBuffer = buffer.replaceNodeWithEntry(nodeIndex, keyIndex, newNodeBuffer[0 ], newNodeBuffer[1 ])
196
+
197
+ if (ownedBy == = owner) {
198
+ buffer = newBuffer
199
+ dataMap = dataMap xor positionMask
200
+ nodeMap = nodeMap xor positionMask
201
+ return this
202
+ }
203
+
204
+ return TrieNode (dataMap xor positionMask, nodeMap xor positionMask, newBuffer)
205
+ }
206
+
184
207
if (ownedBy == = owner) {
185
208
buffer[nodeIndex] = newNode
186
209
return this
@@ -255,6 +278,7 @@ internal class TrieNode<K, V>(
255
278
256
279
private fun removeEntryAtIndex (keyIndex : Int , positionMask : Int ): TrieNode <K , V >? {
257
280
// assert(hasEntryAt(positionMask))
281
+ // It is possible only when this node is the root node
258
282
if (buffer.size == ENTRY_SIZE ) return null
259
283
260
284
val newBuffer = buffer.removeEntryAtIndex(keyIndex)
@@ -296,27 +320,6 @@ internal class TrieNode<K, V>(
296
320
return TrieNode (0 , 0 , newBuffer, mutator.ownership)
297
321
}
298
322
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
-
320
323
private fun collisionContainsKey (key : K ): Boolean {
321
324
for (i in 0 until buffer.size step ENTRY_SIZE ) {
322
325
if (key == buffer[i]) return true
@@ -473,7 +476,7 @@ internal class TrieNode<K, V>(
473
476
} else {
474
477
targetNode.put(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR ) ? : return null
475
478
}
476
- return putResult.replaceNode { node -> updateNodeAtIndex(nodeIndex, node) }
479
+ return putResult.replaceNode { node -> updateNodeAtIndex(nodeIndex, keyPositionMask, node) }
477
480
}
478
481
479
482
// no entry at this key hash segment
@@ -509,7 +512,7 @@ internal class TrieNode<K, V>(
509
512
if (targetNode == = newNode) {
510
513
return this
511
514
}
512
- return mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
515
+ return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
513
516
}
514
517
515
518
// key is absent
@@ -537,11 +540,9 @@ internal class TrieNode<K, V>(
537
540
} else {
538
541
targetNode.remove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR )
539
542
}
540
- return when {
541
- targetNode == = newNode -> this
542
- newNode == null -> removeNodeAtIndex(nodeIndex, keyPositionMask)
543
- else -> updateNodeAtIndex(nodeIndex, newNode)
544
- }
543
+ checkNotNull(newNode)
544
+ if (targetNode == = newNode) return this
545
+ return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
545
546
}
546
547
547
548
// key is absent
@@ -568,11 +569,11 @@ internal class TrieNode<K, V>(
568
569
} else {
569
570
targetNode.mutableRemove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
570
571
}
571
- return when {
572
- targetNode == = newNode -> this
573
- newNode == null -> mutableRemoveNodeAtIndex(nodeIndex, keyPositionMask, mutator.ownership)
574
- else -> mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
572
+ checkNotNull(newNode)
573
+ if (ownedBy == = mutator.ownership || targetNode != = newNode) {
574
+ return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
575
575
}
576
+ return this
576
577
}
577
578
578
579
// key is absent
@@ -599,11 +600,9 @@ internal class TrieNode<K, V>(
599
600
} else {
600
601
targetNode.remove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR )
601
602
}
602
- return when {
603
- targetNode == = newNode -> this
604
- newNode == null -> removeNodeAtIndex(nodeIndex, keyPositionMask)
605
- else -> updateNodeAtIndex(nodeIndex, newNode)
606
- }
603
+ checkNotNull(newNode)
604
+ if (targetNode == = newNode) return this
605
+ return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
607
606
}
608
607
609
608
// key is absent
@@ -630,11 +629,11 @@ internal class TrieNode<K, V>(
630
629
} else {
631
630
targetNode.mutableRemove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
632
631
}
633
- return when {
634
- targetNode == = newNode -> this
635
- newNode == null -> mutableRemoveNodeAtIndex(nodeIndex, keyPositionMask, mutator.ownership)
636
- else -> mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
632
+ checkNotNull(newNode)
633
+ if (ownedBy == = mutator.ownership || targetNode != = newNode) {
634
+ return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
637
635
}
636
+ return this
638
637
}
639
638
640
639
// key is absent
0 commit comments