@@ -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,40 @@ 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
+ // TODO: check how this changes affect `put` and non-collision `remove` operations performance.
175
178
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)
177
187
newBuffer[nodeIndex] = newNode
178
188
return TrieNode (dataMap, nodeMap, newBuffer)
179
189
}
180
190
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 > {
182
192
// assert(buffer[nodeIndex] !== newNode)
183
193
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
+
184
209
if (ownedBy == = owner) {
185
210
buffer[nodeIndex] = newNode
186
211
return this
@@ -255,6 +280,7 @@ internal class TrieNode<K, V>(
255
280
256
281
private fun removeEntryAtIndex (keyIndex : Int , positionMask : Int ): TrieNode <K , V >? {
257
282
// assert(hasEntryAt(positionMask))
283
+ // It is possible only when this node is the root node
258
284
if (buffer.size == ENTRY_SIZE ) return null
259
285
260
286
val newBuffer = buffer.removeEntryAtIndex(keyIndex)
@@ -296,27 +322,6 @@ internal class TrieNode<K, V>(
296
322
return TrieNode (0 , 0 , newBuffer, mutator.ownership)
297
323
}
298
324
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
325
private fun collisionContainsKey (key : K ): Boolean {
321
326
for (i in 0 until buffer.size step ENTRY_SIZE ) {
322
327
if (key == buffer[i]) return true
@@ -473,7 +478,7 @@ internal class TrieNode<K, V>(
473
478
} else {
474
479
targetNode.put(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR ) ? : return null
475
480
}
476
- return putResult.replaceNode { node -> updateNodeAtIndex(nodeIndex, node) }
481
+ return putResult.replaceNode { node -> updateNodeAtIndex(nodeIndex, keyPositionMask, node) }
477
482
}
478
483
479
484
// no entry at this key hash segment
@@ -509,7 +514,7 @@ internal class TrieNode<K, V>(
509
514
if (targetNode == = newNode) {
510
515
return this
511
516
}
512
- return mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
517
+ return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
513
518
}
514
519
515
520
// key is absent
@@ -537,11 +542,9 @@ internal class TrieNode<K, V>(
537
542
} else {
538
543
targetNode.remove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR )
539
544
}
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)
545
548
}
546
549
547
550
// key is absent
@@ -568,11 +571,11 @@ internal class TrieNode<K, V>(
568
571
} else {
569
572
targetNode.mutableRemove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
570
573
}
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)
575
577
}
578
+ return this
576
579
}
577
580
578
581
// key is absent
@@ -599,11 +602,9 @@ internal class TrieNode<K, V>(
599
602
} else {
600
603
targetNode.remove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR )
601
604
}
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)
607
608
}
608
609
609
610
// key is absent
@@ -630,11 +631,11 @@ internal class TrieNode<K, V>(
630
631
} else {
631
632
targetNode.mutableRemove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
632
633
}
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)
637
637
}
638
+ return this
638
639
}
639
640
640
641
// key is absent
0 commit comments