@@ -16,17 +16,6 @@ internal class TrieNode<K, V>(var dataMap: Int,
16
16
17
17
constructor (dataMap: Int , nodeMap: Int , buffer: Array <Any ?>) : this (dataMap, nodeMap, buffer, null )
18
18
19
- fun makeMutableFor (mutator : PersistentHashMapBuilder <* , * >): TrieNode <K , V > {
20
- if (marker == = mutator.marker) { return this }
21
- return TrieNode (dataMap, nodeMap, buffer.copyOf(), mutator.marker)
22
- }
23
-
24
- private fun ensureMutableBy (mutator : PersistentHashMapBuilder <* , * >) {
25
- if (marker != = mutator.marker) {
26
- throw IllegalStateException (" Markers expected to be same" )
27
- }
28
- }
29
-
30
19
internal fun hasDataAt (position : Int ): Boolean {
31
20
return dataMap and position != 0
32
21
}
@@ -72,12 +61,17 @@ internal class TrieNode<K, V>(var dataMap: Int,
72
61
return TrieNode (dataMap or position, nodeMap, newBuffer)
73
62
}
74
63
75
- private fun mutablePutDataAt (position : Int , key : K , value : V ) {
64
+ private fun mutablePutDataAt (position : Int , key : K , value : V , mutatorMarker : Marker ): TrieNode < K , V > {
76
65
// assert(!hasDataAt(position))
77
66
78
67
val keyIndex = keyDataIndex(position)
79
- buffer = bufferPutDataAtIndex(keyIndex, key, value)
80
- dataMap = dataMap or position
68
+ if (marker == = mutatorMarker) {
69
+ buffer = bufferPutDataAtIndex(keyIndex, key, value)
70
+ dataMap = dataMap or position
71
+ return this
72
+ }
73
+ val newBuffer = bufferPutDataAtIndex(keyIndex, key, value)
74
+ return TrieNode (dataMap or position, nodeMap, newBuffer, mutatorMarker)
81
75
}
82
76
83
77
private fun updateValueAtIndex (keyIndex : Int , value : V ): TrieNode <K , V > {
@@ -88,10 +82,17 @@ internal class TrieNode<K, V>(var dataMap: Int,
88
82
return TrieNode (dataMap, nodeMap, newBuffer)
89
83
}
90
84
91
- private fun mutableUpdateValueAtIndex (keyIndex : Int , value : V ): V {
92
- val previousValue = buffer[keyIndex + 1 ]
93
- buffer[keyIndex + 1 ] = value
94
- return previousValue as V
85
+ private fun mutableUpdateValueAtIndex (keyIndex : Int , value : V , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V > {
86
+ // assert(buffer[keyIndex + 1] !== value)
87
+
88
+ mutator.operationResult = buffer[keyIndex + 1 ] as V
89
+ if (marker == = mutator.marker) {
90
+ buffer[keyIndex + 1 ] = value
91
+ return this
92
+ }
93
+ val newBuffer = buffer.copyOf()
94
+ newBuffer[keyIndex + 1 ] = value
95
+ return TrieNode (dataMap, nodeMap, newBuffer, mutator.marker)
95
96
}
96
97
97
98
private fun updateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <K , V >): TrieNode <K , V > {
@@ -102,8 +103,14 @@ internal class TrieNode<K, V>(var dataMap: Int,
102
103
return TrieNode (dataMap, nodeMap, newBuffer)
103
104
}
104
105
105
- private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <K , V >) {
106
- buffer[nodeIndex] = newNode
106
+ private fun mutableUpdateNodeAtIndex (nodeIndex : Int , newNode : TrieNode <K , V >, mutatorMarker : Marker ): TrieNode <K , V > {
107
+ if (marker == = mutatorMarker) {
108
+ buffer[nodeIndex] = newNode
109
+ return this
110
+ }
111
+ val newBuffer = buffer.copyOf()
112
+ newBuffer[nodeIndex] = newNode
113
+ return TrieNode (dataMap, nodeMap, newBuffer, mutatorMarker)
107
114
}
108
115
109
116
private fun bufferMoveDataToNode (keyIndex : Int , position : Int , newKeyHash : Int ,
@@ -134,13 +141,18 @@ internal class TrieNode<K, V>(var dataMap: Int,
134
141
}
135
142
136
143
private fun mutableMoveDataToNode (keyIndex : Int , position : Int , newKeyHash : Int ,
137
- newKey : K , newValue : V , shift : Int , mutator : PersistentHashMapBuilder < * , * >) {
144
+ newKey : K , newValue : V , shift : Int , mutatorMarker : Marker ): TrieNode < K , V > {
138
145
// assert(hasDataAt(position))
139
146
// assert(!hasNodeAt(position))
140
147
141
- buffer = bufferMoveDataToNode(keyIndex, position, newKeyHash, newKey, newValue, shift, mutator.marker)
142
- dataMap = dataMap xor position
143
- nodeMap = nodeMap or position
148
+ if (marker == = mutatorMarker) {
149
+ buffer = bufferMoveDataToNode(keyIndex, position, newKeyHash, newKey, newValue, shift, mutatorMarker)
150
+ dataMap = dataMap xor position
151
+ nodeMap = nodeMap or position
152
+ return this
153
+ }
154
+ val newBuffer = bufferMoveDataToNode(keyIndex, position, newKeyHash, newKey, newValue, shift, mutatorMarker)
155
+ return TrieNode (dataMap xor position, nodeMap or position, newBuffer, mutatorMarker)
144
156
}
145
157
146
158
private fun makeNode (keyHash1 : Int , key1 : K , value1 : V ,
@@ -180,12 +192,18 @@ internal class TrieNode<K, V>(var dataMap: Int,
180
192
return TrieNode (dataMap xor position, nodeMap, newBuffer)
181
193
}
182
194
183
- private fun mutableRemoveDataAtIndex (keyIndex : Int , position : Int ): V {
195
+ private fun mutableRemoveDataAtIndex (keyIndex : Int , position : Int , mutator : PersistentHashMapBuilder < K , V > ): TrieNode < K , V > ? {
184
196
// assert(hasDataAt(position))
185
- val previousValue = buffer[keyIndex + 1 ]
186
- buffer = bufferRemoveDataAtIndex(keyIndex)
187
- dataMap = dataMap xor position
188
- return previousValue as V
197
+ mutator.operationResult = buffer[keyIndex + 1 ] as V
198
+ if (buffer.size == 2 ) { return null }
199
+
200
+ if (marker == = mutator.marker) {
201
+ buffer = bufferRemoveDataAtIndex(keyIndex)
202
+ dataMap = dataMap xor position
203
+ return this
204
+ }
205
+ val newBuffer = bufferRemoveDataAtIndex(keyIndex)
206
+ return TrieNode (dataMap xor position, nodeMap, newBuffer, mutator.marker)
189
207
}
190
208
191
209
private fun collisionRemoveDataAtIndex (i : Int ): TrieNode <K , V >? {
@@ -195,10 +213,16 @@ internal class TrieNode<K, V>(var dataMap: Int,
195
213
return TrieNode (0 , 0 , newBuffer)
196
214
}
197
215
198
- private fun mutableCollisionRemoveDataAtIndex (i : Int ): V ? {
199
- val previousValue = buffer[i + 1 ]
200
- buffer = bufferRemoveDataAtIndex(i)
201
- return previousValue as V
216
+ private fun mutableCollisionRemoveDataAtIndex (i : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V >? {
217
+ mutator.operationResult = buffer[i + 1 ] as V
218
+ if (buffer.size == 2 ) { return null }
219
+
220
+ if (marker == = mutator.marker) {
221
+ buffer = bufferRemoveDataAtIndex(i)
222
+ return this
223
+ }
224
+ val newBuffer = bufferRemoveDataAtIndex(i)
225
+ return TrieNode (0 , 0 , newBuffer, mutator.marker)
202
226
}
203
227
204
228
private fun bufferRemoveNodeAtIndex (nodeIndex : Int ): Array <Any ?> {
@@ -216,10 +240,17 @@ internal class TrieNode<K, V>(var dataMap: Int,
216
240
return TrieNode (dataMap, nodeMap xor position, newBuffer)
217
241
}
218
242
219
- private fun mutableRemoveNodeAtIndex (nodeIndex : Int , position : Int ) {
243
+ private fun mutableRemoveNodeAtIndex (nodeIndex : Int , position : Int , mutatorMarker : Marker ): TrieNode < K , V > ? {
220
244
// assert(hasNodeAt(position))
221
- buffer = bufferRemoveNodeAtIndex(nodeIndex)
222
- nodeMap = nodeMap xor position
245
+ if (buffer.size == 1 ) { return null }
246
+
247
+ if (marker == = mutatorMarker) {
248
+ buffer = bufferRemoveNodeAtIndex(nodeIndex)
249
+ nodeMap = nodeMap xor position
250
+ return this
251
+ }
252
+ val newBuffer = bufferRemoveNodeAtIndex(nodeIndex)
253
+ return TrieNode (dataMap, nodeMap xor position, newBuffer, mutatorMarker)
223
254
}
224
255
225
256
private fun collisionContainsKey (key : K ): Boolean {
@@ -253,17 +284,23 @@ internal class TrieNode<K, V>(var dataMap: Int,
253
284
return TrieNode (0 , 0 , newBuffer)
254
285
}
255
286
256
- private fun mutableCollisionPut (key : K , value : V , mutator : PersistentHashMapBuilder <* , * >): V ? {
287
+ private fun mutableCollisionPut (key : K , value : V , mutator : PersistentHashMapBuilder <K , V >): TrieNode < K , V > {
257
288
for (i in 0 until buffer.size step ENTRY_SIZE ) {
258
289
if (key == buffer[i]) {
259
- val previousValue = buffer[i + 1 ]
260
- buffer[i + 1 ] = value
261
- return previousValue as V
290
+ mutator.operationResult = buffer[i + 1 ] as V
291
+
292
+ if (marker == = mutator.marker) {
293
+ buffer[i + 1 ] = value
294
+ return this
295
+ }
296
+ val newBuffer = buffer.copyOf()
297
+ newBuffer[i + 1 ] = value
298
+ return TrieNode (0 , 0 , newBuffer, mutator.marker)
262
299
}
263
300
}
264
301
mutator.size++
265
- buffer = bufferPutDataAtIndex(0 , key, value)
266
- return null
302
+ val newBuffer = bufferPutDataAtIndex(0 , key, value)
303
+ return TrieNode ( 0 , 0 , newBuffer, mutator.marker)
267
304
}
268
305
269
306
private fun collisionRemove (key : K ): TrieNode <K , V >? {
@@ -275,14 +312,14 @@ internal class TrieNode<K, V>(var dataMap: Int,
275
312
return this
276
313
}
277
314
278
- private fun mutableCollisionRemove (key : K , mutator : PersistentHashMapBuilder <* , * >): V ? {
315
+ private fun mutableCollisionRemove (key : K , mutator : PersistentHashMapBuilder <K , V >): TrieNode < K , V > ? {
279
316
for (i in 0 until buffer.size step ENTRY_SIZE ) {
280
317
if (key == buffer[i]) {
281
318
mutator.size--
282
- return mutableCollisionRemoveDataAtIndex(i)
319
+ return mutableCollisionRemoveDataAtIndex(i, mutator )
283
320
}
284
321
}
285
- return null
322
+ return this
286
323
}
287
324
288
325
private fun collisionRemove (key : K , value : V ): TrieNode <K , V >? {
@@ -368,36 +405,34 @@ internal class TrieNode<K, V>(var dataMap: Int,
368
405
return putDataAt(keyPosition, key, value)
369
406
}
370
407
371
- fun mutablePut (keyHash : Int , key : K , value : @UnsafeVariance V , shift : Int , mutator : PersistentHashMapBuilder <* , * >): V ? {
372
- ensureMutableBy(mutator)
408
+ fun mutablePut (keyHash : Int , key : K , value : @UnsafeVariance V , shift : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V > {
373
409
val keyPosition = 1 shl ((keyHash shr shift) and MAX_BRANCHING_FACTOR_MINUS_ONE )
374
410
375
411
if (hasDataAt(keyPosition)) { // key is directly in buffer
376
412
val keyIndex = keyDataIndex(keyPosition)
377
413
378
414
if (key == keyAtIndex(keyIndex)) {
379
- return mutableUpdateValueAtIndex(keyIndex, value)
415
+ return mutableUpdateValueAtIndex(keyIndex, value, mutator )
380
416
}
381
417
mutator.size++
382
- mutableMoveDataToNode(keyIndex, keyPosition, keyHash, key, value, shift, mutator)
383
- return null
418
+ return mutableMoveDataToNode(keyIndex, keyPosition, keyHash, key, value, shift, mutator.marker)
384
419
}
385
420
if (hasNodeAt(keyPosition)) { // key is in node
386
421
val nodeIndex = keyNodeIndex(keyPosition)
387
422
388
- val targetNode = nodeAtIndex(nodeIndex).makeMutableFor(mutator)
389
- mutableUpdateNodeAtIndex(nodeIndex, targetNode)
390
- return if (shift == MAX_SHIFT ) {
423
+ val targetNode = nodeAtIndex(nodeIndex)
424
+ val newNode = if (shift == MAX_SHIFT ) {
391
425
targetNode.mutableCollisionPut(key, value, mutator)
392
426
} else {
393
427
targetNode.mutablePut(keyHash, key, value, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
394
428
}
429
+ if (targetNode == = newNode) { return this }
430
+ return mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.marker)
395
431
}
396
432
397
433
// key is absent
398
434
mutator.size++
399
- mutablePutDataAt(keyPosition, key, value)
400
- return null
435
+ return mutablePutDataAt(keyPosition, key, value, mutator.marker)
401
436
}
402
437
403
438
fun remove (keyHash : Int , key : K , shift : Int ): TrieNode <K , V >? {
@@ -429,35 +464,34 @@ internal class TrieNode<K, V>(var dataMap: Int,
429
464
return this
430
465
}
431
466
432
- fun mutableRemove (keyHash : Int , key : K , shift : Int , mutator : PersistentHashMapBuilder <* , * >): V ? {
433
- ensureMutableBy(mutator)
467
+ fun mutableRemove (keyHash : Int , key : K , shift : Int , mutator : PersistentHashMapBuilder <K , V >): TrieNode <K , V >? {
434
468
val keyPosition = 1 shl ((keyHash shr shift) and MAX_BRANCHING_FACTOR_MINUS_ONE )
435
469
436
470
if (hasDataAt(keyPosition)) { // key is directly in buffer
437
471
val keyIndex = keyDataIndex(keyPosition)
438
472
439
473
if (key == keyAtIndex(keyIndex)) {
440
474
mutator.size--
441
- return mutableRemoveDataAtIndex(keyIndex, keyPosition)
475
+ return mutableRemoveDataAtIndex(keyIndex, keyPosition, mutator )
442
476
}
443
- return null
477
+ return this
444
478
}
445
479
if (hasNodeAt(keyPosition)) { // key is in node
446
480
val nodeIndex = keyNodeIndex(keyPosition)
447
481
448
- val targetNode = nodeAtIndex(nodeIndex).makeMutableFor(mutator)
449
- mutableUpdateNodeAtIndex(nodeIndex, targetNode)
450
- val previousValue = if (shift == MAX_SHIFT ) {
482
+ val targetNode = nodeAtIndex(nodeIndex)
483
+ val newNode = if (shift == MAX_SHIFT ) {
451
484
targetNode.mutableCollisionRemove(key, mutator)
452
485
} else {
453
486
targetNode.mutableRemove(keyHash, key, shift + LOG_MAX_BRANCHING_FACTOR , mutator)
454
487
}
455
- if (targetNode.buffer.isEmpty()) { mutableRemoveNodeAtIndex(nodeIndex, keyPosition) }
456
- return previousValue
488
+ if (targetNode == = newNode) { return this }
489
+ if (newNode == null ) { return mutableRemoveNodeAtIndex(nodeIndex, keyPosition, mutator.marker) }
490
+ return mutableUpdateNodeAtIndex(nodeIndex, newNode, mutator.marker)
457
491
}
458
492
459
493
// key is absent
460
- return null
494
+ return this
461
495
}
462
496
463
497
fun remove (keyHash : Int , key : K , value : @UnsafeVariance V , shift : Int ): TrieNode <K , V >? {
0 commit comments