@@ -58,6 +58,13 @@ private fun Array<Any?>.removeEntryAtIndex(keyIndex: Int): Array<Any?> {
58
58
return newBuffer
59
59
}
60
60
61
+ private fun Array<Any?>.removeNodeAtIndex (nodeIndex : Int ): Array <Any ?> {
62
+ val newBuffer = arrayOfNulls<Any ?>(this .size - 1 )
63
+ this .copyInto(newBuffer, endIndex = nodeIndex)
64
+ this .copyInto(newBuffer, nodeIndex, startIndex = nodeIndex + 1 , endIndex = this .size)
65
+ return newBuffer
66
+ }
67
+
61
68
62
69
63
70
internal class TrieNode <K , V >(
@@ -194,28 +201,14 @@ internal class TrieNode<K, V>(
194
201
}
195
202
196
203
/* * The given [newNode] must not be a part of any persistent map instance. */
197
- private fun mutableUpdateNodeAtIndex (nodeIndex : Int , positionMask : Int , newNode : TrieNode <K , V >, owner : MutabilityOwnership ): TrieNode <K , V > {
204
+ private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <K , V >, owner : MutabilityOwnership ): TrieNode <K , V > {
198
205
// assert(buffer[nodeIndex] !== newNode)
199
206
200
- val newNodeBuffer = newNode.buffer
201
- if (newNodeBuffer.size == 2 && newNode.nodeMap == 0 ) {
202
- if (buffer.size == 1 ) {
203
- // assert(dataMap == 0 && nodeMap xor positionMask == 0)
204
- newNode.dataMap = nodeMap
205
- return newNode
206
- }
207
-
208
- val keyIndex = entryKeyIndex(positionMask)
209
- val newBuffer = buffer.replaceNodeWithEntry(nodeIndex, keyIndex, newNodeBuffer[0 ], newNodeBuffer[1 ])
210
-
211
- if (ownedBy == = owner) {
212
- buffer = newBuffer
213
- dataMap = dataMap xor positionMask
214
- nodeMap = nodeMap xor positionMask
215
- return this
216
- }
217
-
218
- return TrieNode (dataMap xor positionMask, nodeMap xor positionMask, newBuffer)
207
+ // nodes (including collision nodes) that have only one entry are upped if they have no siblings
208
+ if (buffer.size == 1 && newNode.buffer.size == ENTRY_SIZE && newNode.nodeMap == 0 ) {
209
+ // assert(dataMap == 0 && nodeMap xor positionMask == 0)
210
+ newNode.dataMap = nodeMap
211
+ return newNode
219
212
}
220
213
221
214
if (ownedBy == = owner) {
@@ -227,6 +220,28 @@ internal class TrieNode<K, V>(
227
220
return TrieNode (dataMap, nodeMap, newBuffer, owner)
228
221
}
229
222
223
+ private fun removeNodeAtIndex (nodeIndex : Int , positionMask : Int ): TrieNode <K , V >? {
224
+ // assert(hasNodeAt(positionMask))
225
+ if (buffer.size == 1 ) return null
226
+
227
+ val newBuffer = buffer.removeNodeAtIndex(nodeIndex)
228
+ return TrieNode (dataMap, nodeMap xor positionMask, newBuffer)
229
+ }
230
+
231
+ private fun mutableRemoveNodeAtIndex (nodeIndex : Int , positionMask : Int , owner : MutabilityOwnership ): TrieNode <K , V >? {
232
+ // assert(hasNodeAt(positionMask))
233
+ if (buffer.size == 1 ) return null
234
+
235
+ if (ownedBy == = owner) {
236
+ buffer = buffer.removeNodeAtIndex(nodeIndex)
237
+ nodeMap = nodeMap xor positionMask
238
+ return this
239
+ }
240
+ val newBuffer = buffer.removeNodeAtIndex(nodeIndex)
241
+ return TrieNode (dataMap, nodeMap xor positionMask, newBuffer, owner)
242
+ }
243
+
244
+
230
245
private fun bufferMoveEntryToNode (keyIndex : Int , positionMask : Int , newKeyHash : Int ,
231
246
newKey : K , newValue : V , shift : Int , owner : MutabilityOwnership ? ): Array <Any ?> {
232
247
val storedKey = keyAtIndex(keyIndex)
@@ -290,18 +305,18 @@ internal class TrieNode<K, V>(
290
305
return TrieNode (0 , 1 shl setBit1, arrayOf<Any ?>(node), owner)
291
306
}
292
307
293
- private fun removeEntryAtIndex (keyIndex : Int , positionMask : Int ): TrieNode <K , V > {
308
+ private fun removeEntryAtIndex (keyIndex : Int , positionMask : Int ): TrieNode <K , V >? {
294
309
// assert(hasEntryAt(positionMask))
295
- // assert (buffer.size > ENTRY_SIZE) // can be false only for the root node
310
+ if (buffer.size == ENTRY_SIZE ) return null
296
311
val newBuffer = buffer.removeEntryAtIndex(keyIndex)
297
312
return TrieNode (dataMap xor positionMask, nodeMap, newBuffer)
298
313
}
299
314
300
- private fun mutableRemoveEntryAtIndex (keyIndex : Int , positionMask : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V > {
315
+ private fun mutableRemoveEntryAtIndex (keyIndex : Int , positionMask : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V >? {
301
316
// assert(hasEntryAt(positionMask))
302
- // assert(buffer.size > ENTRY_SIZE)
303
317
mutator.size--
304
318
mutator.operationResult = valueAtKeyIndex(keyIndex)
319
+ if (buffer.size == ENTRY_SIZE ) return null
305
320
306
321
if (ownedBy == = mutator.ownership) {
307
322
buffer = buffer.removeEntryAtIndex(keyIndex)
@@ -312,16 +327,16 @@ internal class TrieNode<K, V>(
312
327
return TrieNode (dataMap xor positionMask, nodeMap, newBuffer, mutator.ownership)
313
328
}
314
329
315
- private fun collisionRemoveEntryAtIndex (i : Int ): TrieNode <K , V > {
316
- // assert (buffer.size > ENTRY_SIZE)
330
+ private fun collisionRemoveEntryAtIndex (i : Int ): TrieNode <K , V >? {
331
+ if (buffer.size == ENTRY_SIZE ) return null
317
332
val newBuffer = buffer.removeEntryAtIndex(i)
318
333
return TrieNode (0 , 0 , newBuffer)
319
334
}
320
335
321
- private fun mutableCollisionRemoveEntryAtIndex (i : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V > {
322
- // assert(buffer.size > ENTRY_SIZE)
336
+ private fun mutableCollisionRemoveEntryAtIndex (i : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V >? {
323
337
mutator.size--
324
338
mutator.operationResult = valueAtKeyIndex(i)
339
+ if (buffer.size == ENTRY_SIZE ) return null
325
340
326
341
if (ownedBy == = mutator.ownership) {
327
342
buffer = buffer.removeEntryAtIndex(i)
@@ -388,7 +403,7 @@ internal class TrieNode<K, V>(
388
403
return TrieNode (0 , 0 , newBuffer, mutator.ownership)
389
404
}
390
405
391
- private fun collisionRemove (key : K ): TrieNode <K , V > {
406
+ private fun collisionRemove (key : K ): TrieNode <K , V >? {
392
407
for (i in 0 until buffer.size step ENTRY_SIZE ) {
393
408
if (key == keyAtIndex(i)) {
394
409
return collisionRemoveEntryAtIndex(i)
@@ -397,7 +412,7 @@ internal class TrieNode<K, V>(
397
412
return this
398
413
}
399
414
400
- private fun mutableCollisionRemove (key : K , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V > {
415
+ private fun mutableCollisionRemove (key : K , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V >? {
401
416
for (i in 0 until buffer.size step ENTRY_SIZE ) {
402
417
if (key == keyAtIndex(i)) {
403
418
return mutableCollisionRemoveEntryAtIndex(i, mutator)
@@ -406,7 +421,7 @@ internal class TrieNode<K, V>(
406
421
return this
407
422
}
408
423
409
- private fun collisionRemove (key : K , value : V ): TrieNode <K , V > {
424
+ private fun collisionRemove (key : K , value : V ): TrieNode <K , V >? {
410
425
for (i in 0 until buffer.size step ENTRY_SIZE ) {
411
426
if (key == keyAtIndex(i) && value == valueAtKeyIndex(i)) {
412
427
return collisionRemoveEntryAtIndex(i)
@@ -415,7 +430,7 @@ internal class TrieNode<K, V>(
415
430
return this
416
431
}
417
432
418
- private fun mutableCollisionRemove (key : K , value : V , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V > {
433
+ private fun mutableCollisionRemove (key : K , value : V , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V >? {
419
434
for (i in 0 until buffer.size step ENTRY_SIZE ) {
420
435
if (key == keyAtIndex(i) && value == valueAtKeyIndex(i)) {
421
436
return mutableCollisionRemoveEntryAtIndex(i, mutator)
@@ -523,15 +538,15 @@ internal class TrieNode<K, V>(
523
538
if (targetNode == = newNode) {
524
539
return this
525
540
}
526
- return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
541
+ return mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
527
542
}
528
543
529
544
// key is absent
530
545
mutator.size++
531
546
return mutableInsertEntryAt(keyPositionMask, key, value, mutator.ownership)
532
547
}
533
548
534
- fun remove (keyHash : Int , key : K , shift : Int ): TrieNode <K , V > {
549
+ fun remove (keyHash : Int , key : K , shift : Int ): TrieNode <K , V >? {
535
550
val keyPositionMask = 1 shl indexSegment(keyHash, shift)
536
551
537
552
if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
@@ -551,15 +566,23 @@ internal class TrieNode<K, V>(
551
566
} else {
552
567
targetNode.remove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR )
553
568
}
554
- if (targetNode == = newNode) return this
555
- return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
569
+ return replaceNode(targetNode, newNode, nodeIndex, keyPositionMask)
556
570
}
557
571
558
572
// key is absent
559
573
return this
560
574
}
561
575
562
- fun mutableRemove (keyHash : Int , key : K , shift : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V > {
576
+ private fun replaceNode (targetNode : TrieNode <K , V >, newNode : TrieNode <K , V >? , nodeIndex : Int , positionMask : Int ) = when {
577
+ newNode == null ->
578
+ removeNodeAtIndex(nodeIndex, positionMask)
579
+ targetNode != = newNode ->
580
+ updateNodeAtIndex(nodeIndex, positionMask, newNode)
581
+ else ->
582
+ this
583
+ }
584
+
585
+ fun mutableRemove (keyHash : Int , key : K , shift : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V >? {
563
586
val keyPositionMask = 1 shl indexSegment(keyHash, shift)
564
587
565
588
if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
@@ -579,17 +602,23 @@ internal class TrieNode<K, V>(
579
602
} else {
580
603
targetNode.mutableRemove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
581
604
}
582
- if (ownedBy == = mutator.ownership || targetNode != = newNode) {
583
- return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
584
- }
585
- return this
605
+ return mutableReplaceNode(targetNode, newNode, nodeIndex, keyPositionMask, mutator.ownership)
586
606
}
587
607
588
608
// key is absent
589
609
return this
590
610
}
591
611
592
- fun remove (keyHash : Int , key : K , value : @UnsafeVariance V , shift : Int ): TrieNode <K , V > {
612
+ private fun mutableReplaceNode (targetNode : TrieNode <K , V >, newNode : TrieNode <K , V >? , nodeIndex : Int , positionMask : Int , owner : MutabilityOwnership ) = when {
613
+ newNode == null ->
614
+ mutableRemoveNodeAtIndex(nodeIndex, positionMask, owner)
615
+ ownedBy == = owner || targetNode != = newNode ->
616
+ mutableUpdateNodeAtIndex(nodeIndex, newNode, owner)
617
+ else ->
618
+ this
619
+ }
620
+
621
+ fun remove (keyHash : Int , key : K , value : @UnsafeVariance V , shift : Int ): TrieNode <K , V >? {
593
622
val keyPositionMask = 1 shl indexSegment(keyHash, shift)
594
623
595
624
if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
@@ -609,15 +638,14 @@ internal class TrieNode<K, V>(
609
638
} else {
610
639
targetNode.remove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR )
611
640
}
612
- if (targetNode == = newNode) return this
613
- return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
641
+ return replaceNode(targetNode, newNode, nodeIndex, keyPositionMask)
614
642
}
615
643
616
644
// key is absent
617
645
return this
618
646
}
619
647
620
- fun mutableRemove (keyHash : Int , key : K , value : @UnsafeVariance V , shift : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V > {
648
+ fun mutableRemove (keyHash : Int , key : K , value : @UnsafeVariance V , shift : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V >? {
621
649
val keyPositionMask = 1 shl indexSegment(keyHash, shift)
622
650
623
651
if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
@@ -637,10 +665,7 @@ internal class TrieNode<K, V>(
637
665
} else {
638
666
targetNode.mutableRemove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
639
667
}
640
- if (ownedBy == = mutator.ownership || targetNode != = newNode) {
641
- return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
642
- }
643
- return this
668
+ return mutableReplaceNode(targetNode, newNode, nodeIndex, keyPositionMask, mutator.ownership)
644
669
}
645
670
646
671
// key is absent
0 commit comments