Fix bytecode optimisations for consequent boxing

This commit is contained in:
Mikhail Zarechenskiy
2018-06-18 10:16:24 +03:00
parent 01d9be65bc
commit 246d5e294c
2 changed files with 25 additions and 8 deletions
@@ -69,6 +69,19 @@ open class BoxingInterpreter(
return when {
insn.isBoxing(generationState) -> {
/*
* It's possible to have chain of several boxings and it's important to retain these boxing methods, consider:
*
* inline class AsAny(val a: Any)
*
* fun takeAny(a: Any)
*
* fun foo() {
* takeAny(AsAny(42)) // valueOf -> AsAny$Erased.box
* }
*
* */
values.markBoxedArgumentValues()
createNewBoxing(insn, value.type, null)
}
insn.isUnboxing(generationState) && firstArg is BoxedBasicValue -> {
@@ -94,16 +107,20 @@ open class BoxingInterpreter(
// N-ary operation should be a method call or multinewarray.
// Arguments for multinewarray could be only numeric,
// so if there are boxed values in args, it's not a case of multinewarray.
for (arg in values) {
if (arg is BoxedBasicValue) {
onMethodCallWithBoxedValue(arg)
}
}
values.markBoxedArgumentValues()
value
}
}
}
private fun List<BasicValue>.markBoxedArgumentValues() {
for (arg in this) {
if (arg is BoxedBasicValue) {
onMethodCallWithBoxedValue(arg)
}
}
}
override fun unaryOperation(insn: AbstractInsnNode, value: BasicValue): BasicValue? {
checkUsedValue(value)
@@ -6,11 +6,11 @@ fun test() {
val a = Result<Int>(1) // valueOf
val b = Result<String>("sample")
val c = Result<Result<Int>>(a) // box
val d = Result<Result<Int>>(Result<Int>(1)) // valueOf, box
val c = Result<Result<Int>>(a)
val d = Result<Result<Int>>(Result<Int>(1)) // valueOf
}
// 2 INVOKESTATIC Result\$Erased.box
// 0 INVOKESTATIC Result\$Erased.box
// 0 INVOKEVIRTUAL Result.unbox
// 2 valueOf