Use specified comparison generator for chars in optimized ranges

Otherwise if Char value is a result of some erased generic call,
coercing it to I (primitive int) causes CCE at run-time.

 #KT-23104 Fixed Target versions 1.2.40
This commit is contained in:
Dmitry Petrov
2018-03-12 15:22:40 +03:00
parent 2891a6c954
commit d38258d7a0
7 changed files with 44 additions and 10 deletions
@@ -35,7 +35,8 @@ interface ComparisonGenerator {
fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator =
when {
type.isRepresentedAsPrimitiveInt() -> IntComparisonGenerator
type == Type.CHAR_TYPE -> CharComparisonGenerator
type.isPrimitiveIntOrCoercible() -> IntComparisonGenerator
type == Type.LONG_TYPE -> LongComparisonGenerator
type == Type.FLOAT_TYPE -> FloatComparisonGenerator
type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
@@ -61,11 +62,11 @@ fun getComparisonGeneratorForRangeContainsCall(
asmElementType == asmValueParameterType ->
getComparisonGeneratorForPrimitiveType(asmElementType)
asmElementType.isRepresentedAsPrimitiveInt() && asmValueParameterType.isRepresentedAsPrimitiveInt() ->
asmElementType.isPrimitiveIntOrCoercible() && asmValueParameterType.isPrimitiveIntOrCoercible() ->
IntComparisonGenerator
asmElementType.isRepresentedAsPrimitiveInt() && asmValueParameterType == Type.LONG_TYPE ||
asmValueParameterType.isRepresentedAsPrimitiveInt() && asmElementType == Type.LONG_TYPE ->
asmElementType.isPrimitiveIntOrCoercible() && asmValueParameterType == Type.LONG_TYPE ||
asmValueParameterType.isPrimitiveIntOrCoercible() && asmElementType == Type.LONG_TYPE ->
LongComparisonGenerator
asmElementType == Type.FLOAT_TYPE && asmValueParameterType == Type.DOUBLE_TYPE ||
@@ -76,5 +77,5 @@ fun getComparisonGeneratorForRangeContainsCall(
}
}
private fun Type.isRepresentedAsPrimitiveInt() =
this == Type.INT_TYPE || this == Type.SHORT_TYPE || this == Type.BYTE_TYPE || this == Type.CHAR_TYPE
private fun Type.isPrimitiveIntOrCoercible() =
this == Type.INT_TYPE || this == Type.SHORT_TYPE || this == Type.BYTE_TYPE
@@ -20,9 +20,7 @@ import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
object IntComparisonGenerator : ComparisonGenerator {
override val comparedType: Type = Type.INT_TYPE
abstract class IntegerComparisonGenerator(override val comparedType: Type) : ComparisonGenerator {
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
v.ificmpge(label)
}
@@ -38,4 +36,8 @@ object IntComparisonGenerator : ComparisonGenerator {
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
v.ificmplt(label)
}
}
}
object IntComparisonGenerator : IntegerComparisonGenerator(Type.INT_TYPE)
object CharComparisonGenerator : IntegerComparisonGenerator(Type.CHAR_TYPE)
@@ -0,0 +1,7 @@
class Cell<T>(val value: T)
fun box(): String =
if (Cell('a').value in 'a'..'z')
"OK"
else
"fail"
@@ -15398,6 +15398,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("genericCharInRangeLiteral.kt")
public void testGenericCharInRangeLiteral() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/genericCharInRangeLiteral.kt");
doTest(fileName);
}
@TestMetadata("inArray.kt")
public void testInArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
@@ -15398,6 +15398,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("genericCharInRangeLiteral.kt")
public void testGenericCharInRangeLiteral() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/genericCharInRangeLiteral.kt");
doTest(fileName);
}
@TestMetadata("inArray.kt")
public void testInArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
@@ -15398,6 +15398,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("genericCharInRangeLiteral.kt")
public void testGenericCharInRangeLiteral() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/genericCharInRangeLiteral.kt");
doTest(fileName);
}
@TestMetadata("inArray.kt")
public void testInArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
@@ -16658,6 +16658,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("genericCharInRangeLiteral.kt")
public void testGenericCharInRangeLiteral() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/genericCharInRangeLiteral.kt");
doTest(fileName);
}
@TestMetadata("inArray.kt")
public void testInArray() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");