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:
+7
-6
@@ -35,7 +35,8 @@ interface ComparisonGenerator {
|
|||||||
|
|
||||||
fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator =
|
fun getComparisonGeneratorForPrimitiveType(type: Type): ComparisonGenerator =
|
||||||
when {
|
when {
|
||||||
type.isRepresentedAsPrimitiveInt() -> IntComparisonGenerator
|
type == Type.CHAR_TYPE -> CharComparisonGenerator
|
||||||
|
type.isPrimitiveIntOrCoercible() -> IntComparisonGenerator
|
||||||
type == Type.LONG_TYPE -> LongComparisonGenerator
|
type == Type.LONG_TYPE -> LongComparisonGenerator
|
||||||
type == Type.FLOAT_TYPE -> FloatComparisonGenerator
|
type == Type.FLOAT_TYPE -> FloatComparisonGenerator
|
||||||
type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
|
type == Type.DOUBLE_TYPE -> DoubleComparisonGenerator
|
||||||
@@ -61,11 +62,11 @@ fun getComparisonGeneratorForRangeContainsCall(
|
|||||||
asmElementType == asmValueParameterType ->
|
asmElementType == asmValueParameterType ->
|
||||||
getComparisonGeneratorForPrimitiveType(asmElementType)
|
getComparisonGeneratorForPrimitiveType(asmElementType)
|
||||||
|
|
||||||
asmElementType.isRepresentedAsPrimitiveInt() && asmValueParameterType.isRepresentedAsPrimitiveInt() ->
|
asmElementType.isPrimitiveIntOrCoercible() && asmValueParameterType.isPrimitiveIntOrCoercible() ->
|
||||||
IntComparisonGenerator
|
IntComparisonGenerator
|
||||||
|
|
||||||
asmElementType.isRepresentedAsPrimitiveInt() && asmValueParameterType == Type.LONG_TYPE ||
|
asmElementType.isPrimitiveIntOrCoercible() && asmValueParameterType == Type.LONG_TYPE ||
|
||||||
asmValueParameterType.isRepresentedAsPrimitiveInt() && asmElementType == Type.LONG_TYPE ->
|
asmValueParameterType.isPrimitiveIntOrCoercible() && asmElementType == Type.LONG_TYPE ->
|
||||||
LongComparisonGenerator
|
LongComparisonGenerator
|
||||||
|
|
||||||
asmElementType == Type.FLOAT_TYPE && asmValueParameterType == Type.DOUBLE_TYPE ||
|
asmElementType == Type.FLOAT_TYPE && asmValueParameterType == Type.DOUBLE_TYPE ||
|
||||||
@@ -76,5 +77,5 @@ fun getComparisonGeneratorForRangeContainsCall(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Type.isRepresentedAsPrimitiveInt() =
|
private fun Type.isPrimitiveIntOrCoercible() =
|
||||||
this == Type.INT_TYPE || this == Type.SHORT_TYPE || this == Type.BYTE_TYPE || this == Type.CHAR_TYPE
|
this == Type.INT_TYPE || this == Type.SHORT_TYPE || this == Type.BYTE_TYPE
|
||||||
+6
-4
@@ -20,9 +20,7 @@ import org.jetbrains.org.objectweb.asm.Label
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
object IntComparisonGenerator : ComparisonGenerator {
|
abstract class IntegerComparisonGenerator(override val comparedType: Type) : ComparisonGenerator {
|
||||||
override val comparedType: Type = Type.INT_TYPE
|
|
||||||
|
|
||||||
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
|
override fun jumpIfGreaterOrEqual(v: InstructionAdapter, label: Label) {
|
||||||
v.ificmpge(label)
|
v.ificmpge(label)
|
||||||
}
|
}
|
||||||
@@ -38,4 +36,8 @@ object IntComparisonGenerator : ComparisonGenerator {
|
|||||||
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
|
override fun jumpIfLess(v: InstructionAdapter, label: Label) {
|
||||||
v.ificmplt(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"
|
||||||
Generated
+6
@@ -15398,6 +15398,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("inArray.kt")
|
||||||
public void testInArray() throws Exception {
|
public void testInArray() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
|
||||||
|
|||||||
+6
@@ -15398,6 +15398,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("inArray.kt")
|
||||||
public void testInArray() throws Exception {
|
public void testInArray() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
|
||||||
|
|||||||
+6
@@ -15398,6 +15398,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("inArray.kt")
|
||||||
public void testInArray() throws Exception {
|
public void testInArray() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
|
||||||
|
|||||||
+6
@@ -16658,6 +16658,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("inArray.kt")
|
||||||
public void testInArray() throws Exception {
|
public void testInArray() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inArray.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user