Skip to content

Commit 5402dd3

Browse files
Abdukodiri KurbonzodaAbduqodiri Qurbonzoda
authored andcommitted
Build new persistent instance only if new changes are applied
1 parent 68b28bf commit 5402dd3

File tree

7 files changed

+70
-46
lines changed

7 files changed

+70
-46
lines changed

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/immutableList/PersistentVector.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ internal class PersistentVector<E>(private val root: Array<Any?>,
201201
}
202202

203203
override fun builder(): PersistentList.Builder<E> {
204-
return PersistentVectorBuilder(root, tail, size, shiftStart)
204+
return PersistentVectorBuilder(this, root, tail, shiftStart)
205205
}
206206

207207
override fun listIterator(index: Int): ListIterator<E> {

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/immutableList/PersistentVectorBuilder.kt

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,33 @@ import kotlinx.collections.immutable.PersistentList
2020

2121
private class Marker
2222

23-
class PersistentVectorBuilder<E>(private var root: Array<Any?>?,
24-
private var tail: Array<Any?>?,
25-
override var size: Int,
23+
class PersistentVectorBuilder<E>(private var vector: PersistentList<E>,
24+
private var vectorRoot: Array<Any?>?,
25+
private var vectorTail: Array<Any?>,
2626
private var shiftStart: Int) : AbstractMutableList<E>(), PersistentList.Builder<E> {
2727
private var marker = Marker()
28+
private var root = vectorRoot
29+
private var tail = vectorTail
30+
override var size = vector.size
2831

2932
override fun build(): PersistentList<E> {
30-
marker = Marker()
31-
if (root == null) {
32-
if (tail == null) {
33-
return persistentVectorOf()
33+
vector = if (root === vectorRoot && tail === vectorTail) {
34+
vector
35+
} else {
36+
marker = Marker()
37+
vectorRoot = root
38+
vectorTail = tail
39+
if (root == null) {
40+
if (tail.isEmpty()) {
41+
persistentVectorOf()
42+
} else {
43+
SmallPersistentVector(tail.copyOf(size))
44+
}
45+
} else {
46+
PersistentVector(root!!, tail, size, shiftStart)
3447
}
35-
return SmallPersistentVector(tail!!.copyOf(size))
3648
}
37-
return PersistentVector(root!!, tail!!, size, shiftStart)
49+
return vector
3850
}
3951

4052
private fun rootSize(): Int {
@@ -71,13 +83,13 @@ class PersistentVectorBuilder<E>(private var root: Array<Any?>?,
7183

7284
val tailSize = size - rootSize()
7385
if (tailSize < MAX_BUFFER_SIZE) {
74-
val mutableLast = makeMutable(tail)
75-
mutableLast[tailSize] = element
76-
this.tail = mutableLast
86+
val mutableTail = makeMutable(tail)
87+
mutableTail[tailSize] = element
88+
this.tail = mutableTail
7789
this.size += 1
7890
} else {
7991
val newTail = mutableBufferWith(element)
80-
this.pushFullTail(root, tail!!, newTail)
92+
this.pushFullTail(root, tail, newTail)
8193
}
8294
return true
8395
}
@@ -149,7 +161,7 @@ class PersistentVectorBuilder<E>(private var root: Array<Any?>?,
149161
this.tail = mutableTail
150162
this.size += 1
151163
} else {
152-
val lastElement = tail!![MAX_BUFFER_SIZE_MINUS_ONE]
164+
val lastElement = tail[MAX_BUFFER_SIZE_MINUS_ONE]
153165
System.arraycopy(tail, index, mutableTail, index + 1, MAX_BUFFER_SIZE_MINUS_ONE - index)
154166
mutableTail[index] = element
155167
pushFullTail(root, mutableTail, mutableBufferWith(lastElement))
@@ -190,7 +202,7 @@ class PersistentVectorBuilder<E>(private var root: Array<Any?>?,
190202

191203
private fun bufferFor(index: Int): Array<Any?> {
192204
if (rootSize() <= index) {
193-
return tail!!
205+
return tail
194206
}
195207
var buffer = root!!
196208
var shift = shiftStart
@@ -211,28 +223,28 @@ class PersistentVectorBuilder<E>(private var root: Array<Any?>?,
211223
if (index >= rootSize) {
212224
return removeFromTail(root, rootSize, shiftStart, index - rootSize) as E
213225
}
214-
val lastElementWrapper = ObjectWrapper(tail!![0])
226+
val lastElementWrapper = ObjectWrapper(tail[0])
215227
val newRoot = removeFromRoot(root!!, shiftStart, index, lastElementWrapper)
216228
removeFromTail(newRoot, rootSize, shiftStart, 0)
217229
return lastElementWrapper.value as E
218230
}
219231

220232
private fun removeFromTail(root: Array<Any?>?, rootSize: Int, shift: Int, index: Int): Any? {
221-
val lastFilledSize = size - rootSize
222-
assert(index < lastFilledSize)
233+
val tailFilledSize = size - rootSize
234+
assert(index < tailFilledSize)
223235

224236
val removedElement: Any?
225-
if (lastFilledSize == 1) {
226-
removedElement = tail!![0]
237+
if (tailFilledSize == 1) {
238+
removedElement = tail[0]
227239
pullLastBufferFromRoot(root, rootSize, shift)
228240
} else {
229-
removedElement = tail!![index]
230-
val mutableLast = makeMutable(tail)
231-
System.arraycopy(tail, index + 1, mutableLast, index, lastFilledSize - index - 1)
232-
mutableLast[lastFilledSize - 1] = null as E
241+
removedElement = tail[index]
242+
val mutableTail = makeMutable(tail)
243+
System.arraycopy(tail, index + 1, mutableTail, index, tailFilledSize - index - 1)
244+
mutableTail[tailFilledSize - 1] = null as E
233245
this.root = root
234-
this.tail = mutableLast
235-
this.size = rootSize + lastFilledSize - 1
246+
this.tail = mutableTail
247+
this.size = rootSize + tailFilledSize - 1
236248
this.shiftStart = shift
237249
}
238250
return removedElement
@@ -268,7 +280,7 @@ class PersistentVectorBuilder<E>(private var root: Array<Any?>?,
268280
private fun pullLastBufferFromRoot(root: Array<Any?>?, rootSize: Int, shift: Int) {
269281
if (shift == 0) {
270282
this.root = null
271-
this.tail = root
283+
this.tail = root ?: emptyArray()
272284
this.size = rootSize
273285
this.shiftStart = shift
274286
return
@@ -313,10 +325,10 @@ class PersistentVectorBuilder<E>(private var root: Array<Any?>?,
313325
throw IndexOutOfBoundsException()
314326
}
315327
if (rootSize() <= index) {
316-
val mutableLast = makeMutable(tail)
317-
val oldElement = mutableLast[index and MAX_BUFFER_SIZE_MINUS_ONE]
318-
mutableLast[index and MAX_BUFFER_SIZE_MINUS_ONE] = element
319-
this.tail = mutableLast
328+
val mutableTail = makeMutable(tail)
329+
val oldElement = mutableTail[index and MAX_BUFFER_SIZE_MINUS_ONE]
330+
mutableTail[index and MAX_BUFFER_SIZE_MINUS_ONE] = element
331+
this.tail = mutableTail
320332
return oldElement as E
321333
}
322334

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ internal class SmallPersistentVector<E>(private val buffer: Array<Any?>) : Immut
125125
}
126126

127127
override fun builder(): PersistentList.Builder<E> {
128-
return PersistentVectorBuilder(null, buffer, size, 0)
128+
return PersistentVectorBuilder(this, null, buffer, 0)
129129
}
130130

131131
override fun indexOf(element: E): Int {

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ internal const val PUT_KEY_VALUE = 2
2424
internal class ModificationWrapper(var value: Int = NO_MODIFICATION)
2525

2626

27-
internal class PersistentHashMap<K, V>(val node: TrieNode<K, V>,
28-
override val size: Int): AbstractMap<K, V>(), PersistentMap<K, V> {
27+
internal class PersistentHashMap<K, V>(internal val node: TrieNode<K, V>,
28+
override val size: Int): AbstractMap<K, V>(), PersistentMap<K, V> {
2929

3030
override val keys: ImmutableSet<K>
3131
get() {
@@ -96,7 +96,7 @@ internal class PersistentHashMap<K, V>(val node: TrieNode<K, V>,
9696
}
9797

9898
override fun builder(): PersistentMap.Builder<K, @UnsafeVariance V> {
99-
return PersistentHashMapBuilder(node, size)
99+
return PersistentHashMapBuilder(this)
100100
}
101101

102102
internal companion object {

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder.kt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,19 @@ import kotlinx.collections.immutable.PersistentMap
2020

2121
internal class Marker
2222

23-
internal class PersistentHashMapBuilder<K, V>(internal var node: TrieNode<K, V>,
24-
override var size: Int) : PersistentMap.Builder<K, V>, AbstractMutableMap<K, V>() {
23+
internal class PersistentHashMapBuilder<K, V>(private var map: PersistentHashMap<K, V>) : PersistentMap.Builder<K, V>, AbstractMutableMap<K, V>() {
2524
internal var marker = Marker()
25+
internal var node = map.node
26+
override var size = map.size
2627

2728
override fun build(): PersistentMap<K, V> {
28-
marker = Marker()
29-
return PersistentHashMap(node, size)
29+
map = if (node === map.node) {
30+
map
31+
} else {
32+
marker = Marker()
33+
PersistentHashMap(node, size)
34+
}
35+
return map
3036
}
3137

3238
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/immutableSet/PersistentHashSet.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package kotlinx.collections.immutable.implementations.immutableSet
1919
import kotlinx.collections.immutable.PersistentSet
2020
import kotlinx.collections.immutable.mutate
2121

22-
internal class PersistentHashSet<E>(private val node: TrieNode<E>,
22+
internal class PersistentHashSet<E>(internal val node: TrieNode<E>,
2323
override val size: Int): AbstractSet<E>(), PersistentSet<E> {
2424
override fun contains(element: E): Boolean {
2525
val hashCode = element?.hashCode() ?: NULL_HASH_CODE
@@ -62,7 +62,7 @@ internal class PersistentHashSet<E>(private val node: TrieNode<E>,
6262
}
6363

6464
override fun builder(): PersistentSet.Builder<E> {
65-
return PersistentHashSetBuilder(node, size)
65+
return PersistentHashSetBuilder(this)
6666
}
6767

6868
internal companion object {

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/immutableSet/PersistentHashSetBuilder.kt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,19 @@ import kotlinx.collections.immutable.PersistentSet
2020

2121
class Marker
2222

23-
internal class PersistentHashSetBuilder<E>(var node: TrieNode<E>,
24-
override var size: Int) : AbstractMutableSet<E>(), PersistentSet.Builder<E> {
23+
internal class PersistentHashSetBuilder<E>(private var set: PersistentHashSet<E>) : AbstractMutableSet<E>(), PersistentSet.Builder<E> {
2524
internal var marker = Marker()
25+
internal var node = set.node
26+
override var size = set.size
2627

2728
override fun build(): PersistentSet<E> {
28-
marker = Marker()
29-
return PersistentHashSet(node, size)
29+
set = if (node === set.node) {
30+
set
31+
} else {
32+
marker = Marker()
33+
PersistentHashSet(node, size)
34+
}
35+
return set
3036
}
3137

3238
override fun contains(element: E): Boolean {

0 commit comments

Comments
 (0)