Files
kotlin/compiler/testData/codegen/bytecodeText/boxingOptimization/kt15862.kt
Dmitry Petrov e0cea468fa KT-15862 Inline generic functions can unexpectedly box primitives
Previous version of the boxing/unboxing analysis treated merging boxed and non-boxed values as a hazard.
If such merged values are not used (e.g., early return + local variables reused in inlined calls),
corresponding boxing/unboxing operations still can be optimized out.

All information related to boxed value usage by instructions is moved to 'BoxedValueDescriptor'.
Introduce "tainted" (and "clean") boxed values, with the following rules:

  merge(B, B) = B, if unboxed types are compatible,
                T, otherwise

  merge(B, X) = T

  merge(T, X) = T

  where
    X is a non-boxed value,
    B is a "clean" boxed value,
    T is a "tainted" boxed value.

Postpone decision about value merge hazards until a "tainted" value is used.
2017-02-06 16:22:26 +03:00

59 lines
1.5 KiB
Kotlin
Vendored

// FILE: test.kt
// @TestKt.class:
// 0 valueOf
// 0 Value\s\(\)
val mask = 127
val entries = IntArray(128)
val flags = BooleanArray(128)
fun distance(index: Int, hash: Int): Int = (128 + index - (hash and mask)) and mask
fun insertSad(x: Int): Boolean {
return insertWithBoxing(
x,
hash = { it },
equals = { a, b -> a == b },
isEmpty = { !flags[it] },
fetch = { entries[it] },
store = { i, x -> entries[i] = x; flags[i] = true; }
)
}
// FILE: inline.kt
inline fun <T> insertWithBoxing(entry: T,
hash: (T) -> Int,
equals: (T, T) -> Boolean,
isEmpty: (Int) -> Boolean,
fetch: (Int) -> T,
store: (Int, T) -> Unit): Boolean {
var currentEntry = entry
var index = hash(entry) and mask
var dist = 0
do {
if (isEmpty(index)) {
store(index, currentEntry)
return true
}
val existingEntry = fetch(index)
if (equals(existingEntry, currentEntry)) {
return false
}
val existingHash = hash(existingEntry)
val existingDistance = distance(index, existingHash)
if (existingDistance < dist) {
store(index, currentEntry)
currentEntry = existingEntry
dist = existingDistance
}
dist += 1
index = (index + 1) and mask
}
while (true)
}