@@ -58,6 +58,13 @@ private fun Array<Any?>.removeEntryAtIndex(keyIndex: Int): Array<Any?> {
5858 return newBuffer
5959}
6060
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+
6168
6269
6370internal class TrieNode <K , V >(
@@ -194,28 +201,14 @@ internal class TrieNode<K, V>(
194201 }
195202
196203 /* * 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 > {
198205// assert(buffer[nodeIndex] !== newNode)
199206
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
219212 }
220213
221214 if (ownedBy == = owner) {
@@ -227,6 +220,28 @@ internal class TrieNode<K, V>(
227220 return TrieNode (dataMap, nodeMap, newBuffer, owner)
228221 }
229222
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+
230245 private fun bufferMoveEntryToNode (keyIndex : Int , positionMask : Int , newKeyHash : Int ,
231246 newKey : K , newValue : V , shift : Int , owner : MutabilityOwnership ? ): Array <Any ?> {
232247 val storedKey = keyAtIndex(keyIndex)
@@ -290,18 +305,18 @@ internal class TrieNode<K, V>(
290305 return TrieNode (0 , 1 shl setBit1, arrayOf<Any ?>(node), owner)
291306 }
292307
293- private fun removeEntryAtIndex (keyIndex : Int , positionMask : Int ): TrieNode <K , V > {
308+ private fun removeEntryAtIndex (keyIndex : Int , positionMask : Int ): TrieNode <K , V >? {
294309// 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
296311 val newBuffer = buffer.removeEntryAtIndex(keyIndex)
297312 return TrieNode (dataMap xor positionMask, nodeMap, newBuffer)
298313 }
299314
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 >? {
301316// assert(hasEntryAt(positionMask))
302- // assert(buffer.size > ENTRY_SIZE)
303317 mutator.size--
304318 mutator.operationResult = valueAtKeyIndex(keyIndex)
319+ if (buffer.size == ENTRY_SIZE ) return null
305320
306321 if (ownedBy == = mutator.ownership) {
307322 buffer = buffer.removeEntryAtIndex(keyIndex)
@@ -312,16 +327,16 @@ internal class TrieNode<K, V>(
312327 return TrieNode (dataMap xor positionMask, nodeMap, newBuffer, mutator.ownership)
313328 }
314329
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
317332 val newBuffer = buffer.removeEntryAtIndex(i)
318333 return TrieNode (0 , 0 , newBuffer)
319334 }
320335
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 >? {
323337 mutator.size--
324338 mutator.operationResult = valueAtKeyIndex(i)
339+ if (buffer.size == ENTRY_SIZE ) return null
325340
326341 if (ownedBy == = mutator.ownership) {
327342 buffer = buffer.removeEntryAtIndex(i)
@@ -388,7 +403,7 @@ internal class TrieNode<K, V>(
388403 return TrieNode (0 , 0 , newBuffer, mutator.ownership)
389404 }
390405
391- private fun collisionRemove (key : K ): TrieNode <K , V > {
406+ private fun collisionRemove (key : K ): TrieNode <K , V >? {
392407 for (i in 0 until buffer.size step ENTRY_SIZE ) {
393408 if (key == keyAtIndex(i)) {
394409 return collisionRemoveEntryAtIndex(i)
@@ -397,7 +412,7 @@ internal class TrieNode<K, V>(
397412 return this
398413 }
399414
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 >? {
401416 for (i in 0 until buffer.size step ENTRY_SIZE ) {
402417 if (key == keyAtIndex(i)) {
403418 return mutableCollisionRemoveEntryAtIndex(i, mutator)
@@ -406,7 +421,7 @@ internal class TrieNode<K, V>(
406421 return this
407422 }
408423
409- private fun collisionRemove (key : K , value : V ): TrieNode <K , V > {
424+ private fun collisionRemove (key : K , value : V ): TrieNode <K , V >? {
410425 for (i in 0 until buffer.size step ENTRY_SIZE ) {
411426 if (key == keyAtIndex(i) && value == valueAtKeyIndex(i)) {
412427 return collisionRemoveEntryAtIndex(i)
@@ -415,7 +430,7 @@ internal class TrieNode<K, V>(
415430 return this
416431 }
417432
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 >? {
419434 for (i in 0 until buffer.size step ENTRY_SIZE ) {
420435 if (key == keyAtIndex(i) && value == valueAtKeyIndex(i)) {
421436 return mutableCollisionRemoveEntryAtIndex(i, mutator)
@@ -523,15 +538,15 @@ internal class TrieNode<K, V>(
523538 if (targetNode == = newNode) {
524539 return this
525540 }
526- return mutableUpdateNodeAtIndex(nodeIndex, keyPositionMask, newNode, mutator.ownership)
541+ return mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.ownership)
527542 }
528543
529544 // key is absent
530545 mutator.size++
531546 return mutableInsertEntryAt(keyPositionMask, key, value, mutator.ownership)
532547 }
533548
534- fun remove (keyHash : Int , key : K , shift : Int ): TrieNode <K , V > {
549+ fun remove (keyHash : Int , key : K , shift : Int ): TrieNode <K , V >? {
535550 val keyPositionMask = 1 shl indexSegment(keyHash, shift)
536551
537552 if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
@@ -551,15 +566,23 @@ internal class TrieNode<K, V>(
551566 } else {
552567 targetNode.remove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR )
553568 }
554- if (targetNode == = newNode) return this
555- return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
569+ return replaceNode(targetNode, newNode, nodeIndex, keyPositionMask)
556570 }
557571
558572 // key is absent
559573 return this
560574 }
561575
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 >? {
563586 val keyPositionMask = 1 shl indexSegment(keyHash, shift)
564587
565588 if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
@@ -579,17 +602,23 @@ internal class TrieNode<K, V>(
579602 } else {
580603 targetNode.mutableRemove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
581604 }
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)
586606 }
587607
588608 // key is absent
589609 return this
590610 }
591611
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 >? {
593622 val keyPositionMask = 1 shl indexSegment(keyHash, shift)
594623
595624 if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
@@ -609,15 +638,14 @@ internal class TrieNode<K, V>(
609638 } else {
610639 targetNode.remove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR )
611640 }
612- if (targetNode == = newNode) return this
613- return updateNodeAtIndex(nodeIndex, keyPositionMask, newNode)
641+ return replaceNode(targetNode, newNode, nodeIndex, keyPositionMask)
614642 }
615643
616644 // key is absent
617645 return this
618646 }
619647
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 >? {
621649 val keyPositionMask = 1 shl indexSegment(keyHash, shift)
622650
623651 if (hasEntryAt(keyPositionMask)) { // key is directly in buffer
@@ -637,10 +665,7 @@ internal class TrieNode<K, V>(
637665 } else {
638666 targetNode.mutableRemove(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
639667 }
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)
644669 }
645670
646671 // key is absent
0 commit comments