KT-16245 Redundant null-check generated for a cast of already non-nullable value

KT-16194 Code with unnecessary safe call contains redundant boxing/unboxing for primitive values
KT-12839 Two null checks are generated when manually null checking platform type

Recognize some additional cases of trivial null checks and trivial instance-of checks.

A variable is "checked for null", if it is:
- a function parameter checked with 'INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull'
- checked for nullability with 'IFNULL/IFNONNULL'
- checked for nullability with 'INSTANCEOF'
  (if objectref is instance-of T, then objectref is non-null)

Before analyzing nullability, introduce synthetic assumptions for execution branches
where a variable is guaranteed to be null or not null. For example, the following bytecode:

     ALOAD 1 // Ljava/lang/String;
     IFNULL L
     <non-null branch>
  L:
     <null branch>

is transformed to

     ALOAD 1
     IFNULL L1
     NEW java/lang/String
     ASTORE 1            // tells analyzer that variable 1 is non-null
     <non-null branch>
  L:
     <null branch>
  L1:
     ACONST_NULL
     ASTORE 1            // tells analyzer that variable 1 is null
     GOTO L

After the analysis is performed on a preprocessed method,
remember the results for "interesting" instructions
and revert the preprocessing transformations.

After that, perform bytecode transformations as usual.

Do not transform INSTANCEOF to-be-reified, because reification at call site
can introduce null checks. E.g.,

    inline fun <reified T> isNullable() = null is T
    ...
    assert(isNullable<String?>())
This commit is contained in:
Dmitry Petrov
2017-02-14 17:45:45 +03:00
parent 3c09a26e16
commit ec403bfdbc
22 changed files with 506 additions and 23 deletions
@@ -12433,6 +12433,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/nullCheckOptimization"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("isNullable.kt")
public void testIsNullable() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/isNullable.kt");
doTest(fileName);
}
@TestMetadata("kt7774.kt")
public void testKt7774() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");