Fix memory leak in MapBuilder #KT-65518
This commit is contained in:
committed by
Space Team
parent
c8e77aad91
commit
20b9ac9d55
@@ -134,11 +134,11 @@ internal class InternalHashMap<K, V> private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(key: K): V? {
|
override fun remove(key: K): V? {
|
||||||
val index = removeKey(key) // mutability gets checked here
|
checkIsMutable()
|
||||||
|
val index = findKey(key)
|
||||||
if (index < 0) return null
|
if (index < 0) return null
|
||||||
val valuesArray = valuesArray!!
|
val oldValue = valuesArray!![index]
|
||||||
val oldValue = valuesArray[index]
|
removeEntryAt(index)
|
||||||
valuesArray.resetAt(index)
|
|
||||||
return oldValue
|
return oldValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,16 +348,9 @@ internal class InternalHashMap<K, V> private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeKey(key: K): Int {
|
private fun removeEntryAt(index: Int) {
|
||||||
checkIsMutable()
|
|
||||||
val index = findKey(key)
|
|
||||||
if (index < 0) return TOMBSTONE
|
|
||||||
removeKeyAt(index)
|
|
||||||
return index
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun removeKeyAt(index: Int) {
|
|
||||||
keysArray.resetAt(index)
|
keysArray.resetAt(index)
|
||||||
|
valuesArray?.resetAt(index)
|
||||||
removeHashAt(presenceArray[index])
|
removeHashAt(presenceArray[index])
|
||||||
presenceArray[index] = TOMBSTONE
|
presenceArray[index] = TOMBSTONE
|
||||||
_size--
|
_size--
|
||||||
@@ -459,7 +452,7 @@ internal class InternalHashMap<K, V> private constructor(
|
|||||||
val index = findKey(entry.key)
|
val index = findKey(entry.key)
|
||||||
if (index < 0) return false
|
if (index < 0) return false
|
||||||
if (valuesArray!![index] != entry.value) return false
|
if (valuesArray!![index] != entry.value) return false
|
||||||
removeKeyAt(index)
|
removeEntryAt(index)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,7 +460,7 @@ internal class InternalHashMap<K, V> private constructor(
|
|||||||
checkIsMutable()
|
checkIsMutable()
|
||||||
val index = findValue(value)
|
val index = findValue(value)
|
||||||
if (index < 0) return false
|
if (index < 0) return false
|
||||||
removeKeyAt(index)
|
removeEntryAt(index)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +501,7 @@ internal class InternalHashMap<K, V> private constructor(
|
|||||||
checkForComodification()
|
checkForComodification()
|
||||||
check(lastIndex != -1) { "Call next() before removing element from the iterator." }
|
check(lastIndex != -1) { "Call next() before removing element from the iterator." }
|
||||||
map.checkIsMutable()
|
map.checkIsMutable()
|
||||||
map.removeKeyAt(lastIndex)
|
map.removeEntryAt(lastIndex)
|
||||||
lastIndex = -1
|
lastIndex = -1
|
||||||
expectedModCount = map.modCount
|
expectedModCount = map.modCount
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,11 +102,11 @@ internal class MapBuilder<K, V> private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(key: K): V? {
|
override fun remove(key: K): V? {
|
||||||
val index = removeKey(key) // mutability gets checked here
|
checkIsMutable()
|
||||||
|
val index = findKey(key)
|
||||||
if (index < 0) return null
|
if (index < 0) return null
|
||||||
val valuesArray = valuesArray!!
|
val oldValue = valuesArray!![index]
|
||||||
val oldValue = valuesArray[index]
|
removeEntryAt(index)
|
||||||
valuesArray.resetAt(index)
|
|
||||||
return oldValue
|
return oldValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,16 +342,17 @@ internal class MapBuilder<K, V> private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun removeKey(key: K): Int {
|
internal fun removeKey(key: K): Boolean {
|
||||||
checkIsMutable()
|
checkIsMutable()
|
||||||
val index = findKey(key)
|
val index = findKey(key)
|
||||||
if (index < 0) return TOMBSTONE
|
if (index < 0) return false
|
||||||
removeKeyAt(index)
|
removeEntryAt(index)
|
||||||
return index
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeKeyAt(index: Int) {
|
private fun removeEntryAt(index: Int) {
|
||||||
keysArray.resetAt(index)
|
keysArray.resetAt(index)
|
||||||
|
valuesArray?.resetAt(index)
|
||||||
removeHashAt(presenceArray[index])
|
removeHashAt(presenceArray[index])
|
||||||
presenceArray[index] = TOMBSTONE
|
presenceArray[index] = TOMBSTONE
|
||||||
size--
|
size--
|
||||||
@@ -463,7 +464,7 @@ internal class MapBuilder<K, V> private constructor(
|
|||||||
val index = findKey(entry.key)
|
val index = findKey(entry.key)
|
||||||
if (index < 0) return false
|
if (index < 0) return false
|
||||||
if (valuesArray!![index] != entry.value) return false
|
if (valuesArray!![index] != entry.value) return false
|
||||||
removeKeyAt(index)
|
removeEntryAt(index)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,7 +472,7 @@ internal class MapBuilder<K, V> private constructor(
|
|||||||
checkIsMutable()
|
checkIsMutable()
|
||||||
val index = findValue(element)
|
val index = findValue(element)
|
||||||
if (index < 0) return false
|
if (index < 0) return false
|
||||||
removeKeyAt(index)
|
removeEntryAt(index)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,7 +515,7 @@ internal class MapBuilder<K, V> private constructor(
|
|||||||
checkForComodification()
|
checkForComodification()
|
||||||
check(lastIndex != -1) { "Call next() before removing element from the iterator." }
|
check(lastIndex != -1) { "Call next() before removing element from the iterator." }
|
||||||
map.checkIsMutable()
|
map.checkIsMutable()
|
||||||
map.removeKeyAt(lastIndex)
|
map.removeEntryAt(lastIndex)
|
||||||
lastIndex = -1
|
lastIndex = -1
|
||||||
expectedModCount = map.modCount
|
expectedModCount = map.modCount
|
||||||
}
|
}
|
||||||
@@ -618,7 +619,7 @@ internal class MapBuilderKeys<E> internal constructor(
|
|||||||
override fun clear() = backing.clear()
|
override fun clear() = backing.clear()
|
||||||
override fun add(element: E): Boolean = throw UnsupportedOperationException()
|
override fun add(element: E): Boolean = throw UnsupportedOperationException()
|
||||||
override fun addAll(elements: Collection<E>): Boolean = throw UnsupportedOperationException()
|
override fun addAll(elements: Collection<E>): Boolean = throw UnsupportedOperationException()
|
||||||
override fun remove(element: E): Boolean = backing.removeKey(element) >= 0
|
override fun remove(element: E): Boolean = backing.removeKey(element)
|
||||||
override fun iterator(): MutableIterator<E> = backing.keysIterator()
|
override fun iterator(): MutableIterator<E> = backing.keysIterator()
|
||||||
|
|
||||||
override fun removeAll(elements: Collection<E>): Boolean {
|
override fun removeAll(elements: Collection<E>): Boolean {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ internal class SetBuilder<E> internal constructor(
|
|||||||
override fun contains(element: E): Boolean = backing.containsKey(element)
|
override fun contains(element: E): Boolean = backing.containsKey(element)
|
||||||
override fun clear() = backing.clear()
|
override fun clear() = backing.clear()
|
||||||
override fun add(element: E): Boolean = backing.addKey(element) >= 0
|
override fun add(element: E): Boolean = backing.addKey(element) >= 0
|
||||||
override fun remove(element: E): Boolean = backing.removeKey(element) >= 0
|
override fun remove(element: E): Boolean = backing.removeKey(element)
|
||||||
override fun iterator(): MutableIterator<E> = backing.keysIterator()
|
override fun iterator(): MutableIterator<E> = backing.keysIterator()
|
||||||
|
|
||||||
override fun addAll(elements: Collection<E>): Boolean {
|
override fun addAll(elements: Collection<E>): Boolean {
|
||||||
|
|||||||
@@ -136,11 +136,11 @@ public actual class HashMap<K, V> private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override actual fun remove(key: K): V? {
|
override actual fun remove(key: K): V? {
|
||||||
val index = removeKey(key) // mutability gets checked here
|
checkIsMutable()
|
||||||
|
val index = findKey(key)
|
||||||
if (index < 0) return null
|
if (index < 0) return null
|
||||||
val valuesArray = valuesArray!!
|
val oldValue = valuesArray!![index]
|
||||||
val oldValue = valuesArray[index]
|
removeEntryAt(index)
|
||||||
valuesArray.resetAt(index)
|
|
||||||
return oldValue
|
return oldValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,16 +379,17 @@ public actual class HashMap<K, V> private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun removeKey(key: K): Int {
|
internal fun removeKey(key: K): Boolean {
|
||||||
checkIsMutable()
|
checkIsMutable()
|
||||||
val index = findKey(key)
|
val index = findKey(key)
|
||||||
if (index < 0) return TOMBSTONE
|
if (index < 0) return false
|
||||||
removeKeyAt(index)
|
removeEntryAt(index)
|
||||||
return index
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeKeyAt(index: Int) {
|
private fun removeEntryAt(index: Int) {
|
||||||
keysArray.resetAt(index)
|
keysArray.resetAt(index)
|
||||||
|
valuesArray?.resetAt(index)
|
||||||
removeHashAt(presenceArray[index])
|
removeHashAt(presenceArray[index])
|
||||||
presenceArray[index] = TOMBSTONE
|
presenceArray[index] = TOMBSTONE
|
||||||
_size--
|
_size--
|
||||||
@@ -518,7 +519,7 @@ public actual class HashMap<K, V> private constructor(
|
|||||||
val index = findKey(entry.key)
|
val index = findKey(entry.key)
|
||||||
if (index < 0) return false
|
if (index < 0) return false
|
||||||
if (valuesArray!![index] != entry.value) return false
|
if (valuesArray!![index] != entry.value) return false
|
||||||
removeKeyAt(index)
|
removeEntryAt(index)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,7 +527,7 @@ public actual class HashMap<K, V> private constructor(
|
|||||||
checkIsMutable()
|
checkIsMutable()
|
||||||
val index = findValue(element)
|
val index = findValue(element)
|
||||||
if (index < 0) return false
|
if (index < 0) return false
|
||||||
removeKeyAt(index)
|
removeEntryAt(index)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -577,7 +578,7 @@ public actual class HashMap<K, V> private constructor(
|
|||||||
checkForComodification()
|
checkForComodification()
|
||||||
check(lastIndex != -1) { "Call next() before removing element from the iterator." }
|
check(lastIndex != -1) { "Call next() before removing element from the iterator." }
|
||||||
map.checkIsMutable()
|
map.checkIsMutable()
|
||||||
map.removeKeyAt(lastIndex)
|
map.removeEntryAt(lastIndex)
|
||||||
lastIndex = -1
|
lastIndex = -1
|
||||||
expectedModCount = map.modCount
|
expectedModCount = map.modCount
|
||||||
}
|
}
|
||||||
@@ -682,7 +683,7 @@ internal class HashMapKeys<E> internal constructor(
|
|||||||
override fun clear() = backing.clear()
|
override fun clear() = backing.clear()
|
||||||
override fun add(element: E): Boolean = throw UnsupportedOperationException()
|
override fun add(element: E): Boolean = throw UnsupportedOperationException()
|
||||||
override fun addAll(elements: Collection<E>): Boolean = throw UnsupportedOperationException()
|
override fun addAll(elements: Collection<E>): Boolean = throw UnsupportedOperationException()
|
||||||
override fun remove(element: E): Boolean = backing.removeKey(element) >= 0
|
override fun remove(element: E): Boolean = backing.removeKey(element)
|
||||||
override fun iterator(): MutableIterator<E> = backing.keysIterator()
|
override fun iterator(): MutableIterator<E> = backing.keysIterator()
|
||||||
|
|
||||||
override fun removeAll(elements: Collection<E>): Boolean {
|
override fun removeAll(elements: Collection<E>): Boolean {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public actual class HashSet<E> internal constructor(
|
|||||||
override fun getElement(element: E): E? = backing.getKey(element)
|
override fun getElement(element: E): E? = backing.getKey(element)
|
||||||
override actual fun clear(): Unit = backing.clear()
|
override actual fun clear(): Unit = backing.clear()
|
||||||
override actual fun add(element: E): Boolean = backing.addKey(element) >= 0
|
override actual fun add(element: E): Boolean = backing.addKey(element) >= 0
|
||||||
override actual fun remove(element: E): Boolean = backing.removeKey(element) >= 0
|
override actual fun remove(element: E): Boolean = backing.removeKey(element)
|
||||||
override actual fun iterator(): MutableIterator<E> = backing.keysIterator()
|
override actual fun iterator(): MutableIterator<E> = backing.keysIterator()
|
||||||
|
|
||||||
override actual fun addAll(elements: Collection<E>): Boolean {
|
override actual fun addAll(elements: Collection<E>): Boolean {
|
||||||
|
|||||||
Reference in New Issue
Block a user