Derek Peirce
06/17/2023, 3:10 AMval y = x.takeIf { check(x) } ?: 3
Decompiled, it becomes:
Integer var2 = x;
int it = ((Number)var2).intValue();
int var4 = false;
Integer var10000 = check(x) ? var2 : null;
int y = var10000 != null ? var10000 : 3;
Suddenly, our int
is becoming an Integer
, but if the compiler recognized that it could treat Integer
as, say, int value
and boolean hasValue
, it could optimize this code to instead look like:
int x = 2;
int var2 = x;
boolean var4 = false;
int var10000_value;
boolean var10000_hasValue;
if (check(x)) {
var10000_value = var2;
var10000_hasValue = true;
} else {
var10000_value = 0;
var10000_hasValue = false;
}
int y = var10000_hasValue ? var10000_value : 3;
I would expect further compiler passes to eventually optimize this to resemble something close to the ideal:
val y = if (check(x)) x else 3
whose Java code is the similarly compact:
int y = check(x) ? x : 3;
much more easily than it could optimize anything that contains boxing and unboxing.ephemient
06/17/2023, 3:19 AM-XX:EliminateAutoBox
. I haven't looked at the JIT-generated machine code to see if applies in this case, thoughDerek Peirce
06/17/2023, 3:25 AMEliminateAutoBox
, what I did find suggests that it's limited to Integer
, which is strange. I think the best use-case would be Boolean?
, which can be trivially optimized as a 0=false, 1=true, 2=null byte. As a JVM flag, I doubt that EliminateAutoBox
applies to compiling Android apps from Kotlin, though, which my main use-case.Ilmir Usmanov [JB]
06/17/2023, 2:55 PMDerek Peirce
06/18/2023, 4:24 AMval y = x._takeIf_ *{* _check_(x) *}* ?: 3
is decently larger than the bytecode needed for the ideal val y = if (_check_(x)) x else 3
.)