SwitchOptimization: generating `lookupswitch' opcode for 'when' in case of integral types
This commit is contained in:
committed by
Evgeny Gerashchenko
parent
c73533d214
commit
1952781e4b
@@ -26,8 +26,10 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import com.sun.jdi.IntegerValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant;
|
||||
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.jet.codegen.binding.MutableClosure;
|
||||
@@ -3755,9 +3757,9 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
assert conditionExpression != null;
|
||||
|
||||
CompileTimeConstant constant = getCompileTimeConstant(conditionExpression, bindingContext);
|
||||
assert constant != null && constant instanceof IntValue;
|
||||
assert doesConstantFitForSwitch(constant);
|
||||
|
||||
int value = ((IntValue) constant).getValue();
|
||||
int value = (constant.getValue() instanceof Number) ? ((Number)constant.getValue()).intValue() : ((Character)constant.getValue()).charValue();
|
||||
|
||||
if (!transitions.containsKey(value)) {
|
||||
transitions.put(value, entryLabel);
|
||||
@@ -3828,8 +3830,20 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
v.lookupswitch(defaultLabel, keys, labels);
|
||||
}
|
||||
|
||||
private boolean doesConstantFitForSwitch(CompileTimeConstant constant) {
|
||||
if (constant == null || !(constant instanceof IntegerValueConstant)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long value = (constant.getValue() instanceof Number) ? ((Number)constant.getValue()).longValue() : ((Character)constant.getValue()).charValue();
|
||||
return value >= Integer.MIN_VALUE &&
|
||||
value <= Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
private boolean canSwitchBeUsedIn(JetWhenExpression expression, Type subjectType) {
|
||||
if (subjectType.getSort() != Type.INT) {
|
||||
int typeSort = subjectType.getSort();
|
||||
|
||||
if (typeSort != Type.INT && typeSort != Type.CHAR && typeSort != Type.SHORT && typeSort != Type.BYTE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3847,7 +3861,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
}
|
||||
|
||||
CompileTimeConstant constant = getCompileTimeConstant(patternExpression, bindingContext);
|
||||
if (constant == null || !(constant instanceof IntValue)) {
|
||||
if (!doesConstantFitForSwitch(constant)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
fun foo1(x : Int) : Int {
|
||||
return when (x % 10) {
|
||||
1,2,3 -> 1
|
||||
@@ -7,43 +8,44 @@ fun foo1(x : Int) : Int {
|
||||
}
|
||||
}
|
||||
|
||||
fun foo2(x : Int) : Int {
|
||||
when (x % 10) {
|
||||
1,2,3 -> return 1
|
||||
4,5,6 -> return 2
|
||||
7,8,9 -> return 3
|
||||
fun foo2(x : Short) : Int {
|
||||
when ((x % 10).toShort()) {
|
||||
1.toShort(),2.toShort(),3.toShort() -> return 1
|
||||
4.toShort(),5.toShort(),6.toShort() -> return 2
|
||||
7.toShort(),8.toShort(),9.toShort() -> return 3
|
||||
}
|
||||
|
||||
return 4
|
||||
}
|
||||
|
||||
fun foo3(x : Int) : Int {
|
||||
when (x % 10) {
|
||||
1 -> return 1
|
||||
2 -> return 1
|
||||
3 -> return 1
|
||||
4 -> return 2
|
||||
5 -> return 2
|
||||
6 -> return 2
|
||||
7 -> return 3
|
||||
8 -> return 3
|
||||
9 -> return 3
|
||||
fun foo3(x : Char) : Int {
|
||||
|
||||
when (x) {
|
||||
'1' -> return 1
|
||||
'2' -> return 1
|
||||
'3' -> return 1
|
||||
'4' -> return 2
|
||||
'5' -> return 2
|
||||
'6' -> return 2
|
||||
'7' -> return 3
|
||||
'8' -> return 3
|
||||
'9' -> return 3
|
||||
}
|
||||
|
||||
return 4
|
||||
}
|
||||
|
||||
fun foo4(x : Int) : Int {
|
||||
return when (x % 10) {
|
||||
1 -> 1
|
||||
2 -> 1
|
||||
3 -> 1
|
||||
4 -> 2
|
||||
5 -> 2
|
||||
6 -> 2
|
||||
7 -> 3
|
||||
8 -> 3
|
||||
9 -> 3
|
||||
fun foo4(x : Byte) : Int {
|
||||
return when ((x % 10).toByte()) {
|
||||
1.toByte() -> 1
|
||||
2.toByte() -> 1
|
||||
3.toByte() -> 1
|
||||
4.toByte() -> 2
|
||||
5.toByte() -> 2
|
||||
6.toByte() -> 2
|
||||
7.toByte() -> 3
|
||||
8.toByte() -> 3
|
||||
9.toByte() -> 3
|
||||
else -> 4
|
||||
}
|
||||
}
|
||||
@@ -66,9 +68,9 @@ fun test(foo : (Int) -> Int, name : String) : String {
|
||||
|
||||
fun box(): String {
|
||||
val testResult = test({x -> foo1(x)}, "foo1") +
|
||||
test({x -> foo2(x)}, "foo2") +
|
||||
test({x -> foo3(x)}, "foo3") +
|
||||
test({x -> foo4(x)}, "foo4")
|
||||
test({x -> foo2(x.toShort())}, "foo2") +
|
||||
test({x -> foo3((x % 10 + '0'.toInt()).toChar())}, "foo3") +
|
||||
test({x -> foo4(x.toByte())}, "foo4")
|
||||
if (testResult != "") return testResult
|
||||
return "OK"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user