JVM_IR KT-47398 handle @EnhancedNullability String subject as in 1.0

This commit is contained in:
Dmitry Petrov
2021-06-23 13:40:25 +03:00
committed by teamcityserver
parent c26d71c4ef
commit 0104b1275f
8 changed files with 208 additions and 4 deletions
@@ -42767,12 +42767,24 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/when/stringOptimization/duplicatingItemsSameHashCode3.kt");
}
@Test
@TestMetadata("enhancedNullability.kt")
public void testEnhancedNullability() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/enhancedNullability.kt");
}
@Test
@TestMetadata("expression.kt")
public void testExpression() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/expression.kt");
}
@Test
@TestMetadata("flexibleNullability.kt")
public void testFlexibleNullability() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/flexibleNullability.kt");
}
@Test
@TestMetadata("nullability.kt")
public void testNullability() throws Exception {
@@ -9,10 +9,11 @@ import org.jetbrains.kotlin.codegen.`when`.SwitchCodegen.Companion.preferLookupO
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.isTrueConst
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import java.util.*
// TODO: eliminate the temporary variable
class SwitchGenerator(private val expression: IrWhen, private val data: BlockInfo, private val codegen: ExpressionCodegen) {
@@ -446,9 +447,19 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
hashAndSwitchLabels.add(ValueToLabel(key, Label()))
}
// Using a switch, the subject string has to be traversed at least twice (hash + comparison * N, where N is #strings hashed into the
// same bucket). The optimization isn't better than an IF cascade when #switch-targets <= 2.
override fun shouldOptimize() = hashAndSwitchLabels.size > 2
// Using a switch, the subject string has to be traversed at least twice
// (hash + comparison * N, where N is #strings hashed into the same bucket).
// The optimization isn't better than an IF cascade when #switch-targets <= 2.
//
// Generate "optimized" version for @EnhancedNullability subject type
// to model 1.0 behavior causing NPE in case of null value.
// TODO make 'when' with String subject behavior consistent.
// see:
// box/when/stringOptimization/enhancedNullability.kt
// box/when/stringOptimization/flexibleNullability.kt
override fun shouldOptimize() =
hashAndSwitchLabels.size > 2 ||
subject.type.hasAnnotation(JvmAnnotationNames.ENHANCED_NULLABILITY_ANNOTATION) && hashAndSwitchLabels.isNotEmpty()
override fun genSwitch() {
with(codegen) {
+1
View File
@@ -1,4 +1,5 @@
// WITH_RUNTIME
// IGNORE_BACKEND: WASM
enum class EType {
A
@@ -0,0 +1,75 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: enhancedNullability.kt
fun testEmpty() {
when (J.nullString()) {
}
}
fun testSingle() {
try {
var q = "other"
when (J.nullString()) {
"a" -> q = "A"
}
throw Exception("Should throw NPE, got '$q'")
} catch (e: NullPointerException) {
}
}
fun testElseOnly() {
var q = "other"
when (J.nullString()) {
else -> q = "A"
}
if (q != "A") {
throw Exception("Expected: 'A', got '$q'")
}
}
fun testSmall() {
try {
val q = when (J.nullString()) {
"a" -> "A"
else -> "other"
}
throw Exception("Should throw NPE, got '$q'")
} catch (e: NullPointerException) {
}
}
fun testBigger() {
try {
val q = when (J.nullString()) {
"a" -> "A"
"b" -> "B"
"c" -> "C"
"d" -> "D"
"e" -> "E"
"f" -> "F"
"g" -> "G"
"h" -> "H"
else -> "other"
}
throw Exception("Should throw NPE, got '$q'")
} catch (e: NullPointerException) {
}
}
fun box(): String {
testEmpty()
testSingle()
testElseOnly()
testSmall()
testBigger()
return "OK"
}
// FILE: J.java
import org.jetbrains.annotations.NotNull;
public class J {
public static @NotNull String nullString() { return null; }
}
@@ -0,0 +1,71 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: flexibleNullability.kt
fun testEmpty() {
when (J.nullString()) {
}
}
fun testSingle() {
var q = "other"
when (J.nullString()) {
"a" -> q = "A"
}
if (q != "other") {
throw Exception("Expected 'other', got '$q'")
}
}
fun testElseOnly() {
var q = "other"
when (J.nullString()) {
else -> q = "A"
}
if (q != "A") {
throw Exception("Expected: 'A', got '$q'")
}
}
fun testSmall() {
val q = when (J.nullString()) {
"a" -> "A"
else -> "other"
}
if (q != "other") {
throw Exception("Expected 'other', got '$q'")
}
}
fun testBigger() {
val q = when (J.nullString()) {
"a" -> "A"
"b" -> "B"
"c" -> "C"
"d" -> "D"
"e" -> "E"
"f" -> "F"
"g" -> "G"
"h" -> "H"
else -> "other"
}
if (q != "other") {
throw Exception("Expected 'other', got '$q'")
}
}
fun box(): String {
testEmpty()
testSingle()
testElseOnly()
testSmall()
testBigger()
return "OK"
}
// FILE: J.java
public class J {
public static String nullString() { return null; }
}
@@ -42725,12 +42725,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/when/stringOptimization/duplicatingItemsSameHashCode3.kt");
}
@Test
@TestMetadata("enhancedNullability.kt")
public void testEnhancedNullability() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/enhancedNullability.kt");
}
@Test
@TestMetadata("expression.kt")
public void testExpression() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/expression.kt");
}
@Test
@TestMetadata("flexibleNullability.kt")
public void testFlexibleNullability() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/flexibleNullability.kt");
}
@Test
@TestMetadata("nullability.kt")
public void testNullability() throws Exception {
@@ -42767,12 +42767,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/when/stringOptimization/duplicatingItemsSameHashCode3.kt");
}
@Test
@TestMetadata("enhancedNullability.kt")
public void testEnhancedNullability() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/enhancedNullability.kt");
}
@Test
@TestMetadata("expression.kt")
public void testExpression() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/expression.kt");
}
@Test
@TestMetadata("flexibleNullability.kt")
public void testFlexibleNullability() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/flexibleNullability.kt");
}
@Test
@TestMetadata("nullability.kt")
public void testNullability() throws Exception {
@@ -34445,11 +34445,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/when/stringOptimization/duplicatingItemsSameHashCode3.kt");
}
@TestMetadata("enhancedNullability.kt")
public void testEnhancedNullability() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/enhancedNullability.kt");
}
@TestMetadata("expression.kt")
public void testExpression() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/expression.kt");
}
@TestMetadata("flexibleNullability.kt")
public void testFlexibleNullability() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/flexibleNullability.kt");
}
@TestMetadata("nullability.kt")
public void testNullability() throws Exception {
runTest("compiler/testData/codegen/box/when/stringOptimization/nullability.kt");