Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update filter for Kotlin 1.5 when-expressions with String #1172

Merged
merged 6 commits into from Apr 8, 2021

Conversation

Godin
Copy link
Member

@Godin Godin commented Apr 5, 2021

Currently execution of

mvn clean package -Dkotlin.version=1.5.0-M1

leads to

Failed tests:
  execute_assertions_in_comments(org.jacoco.core.test.validation.kotlin.KotlinWhenExpressionTest)

For the following Example.kt

fun example(p: String): Int = when (p) {
    "a" -> 1
    "b" -> 2
    else -> 3
}

(where number of hash codes is less than 3)

Execution of

kotlin/bin/kotlinc Example.kt -d classes
javap -v -p classes/ExampleKt.class

using Kotlin compiler version 1.5-M1 produces bytecode containing only sequence of if-s without tableswitch

  public static final int example(java.lang.String);
    descriptor: (Ljava/lang/String;)I
    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    Code:
      stack=2, locals=2, args_size=1
         0: aload_0
         1: ldc           #9                  // String p
         3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
         6: aload_0
         7: astore_1
         8: aload_1
         9: ldc           #17                 // String a
        11: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
        14: ifeq          21
        17: iconst_1
        18: goto          35
        21: aload_1
        22: ldc           #23                 // String b
        24: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
        27: ifeq          34
        30: iconst_2
        31: goto          35
        34: iconst_3
        35: ireturn
      LineNumberTable:
        line 1: 6
        line 2: 8
        line 3: 21
        line 4: 34
        line 5: 35

Whereas for the following Example.kt

fun example(p: String): Int = when (p) {
    "a" -> 1
    "b" -> 2
    "c" -> 3
    else -> 4
}

(where number of hash codes is 3)

still produces tableswitch

  public static final int example(java.lang.String);
    descriptor: (Ljava/lang/String;)I
    flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    Code:
      stack=2, locals=2, args_size=1
         0: aload_0
         1: ldc           #9                  // String p
         3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
         6: aload_0
         7: astore_1
         8: aload_1
         9: invokevirtual #21                 // Method java/lang/String.hashCode:()I
        12: tableswitch   { // 97 to 99
                      97: 40
                      98: 52
                      99: 64
                 default: 88
            }
        40: aload_1
        41: ldc           #23                 // String a
        43: invokevirtual #27                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        46: ifne          76
        49: goto          88
        52: aload_1
        53: ldc           #29                 // String b
        55: invokevirtual #27                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        58: ifne          80
        61: goto          88
        64: aload_1
        65: ldc           #31                 // String c
        67: invokevirtual #27                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        70: ifne          84
        73: goto          88
        76: iconst_1
        77: goto          89
        80: iconst_2
        81: goto          89
        84: iconst_3
        85: goto          89
        88: iconst_4
        89: ireturn
      LineNumberTable:
        line 1: 6
        line 2: 76
        line 3: 80
        line 4: 84
        line 5: 88
        line 6: 89

However bytecode is different from the one recognized by

public final class KotlinWhenStringFilter implements IFilter {

But it is almost recognized by

public final class StringSwitchEcjFilter implements IFilter {


And all this seems to be related to the following change in Kotlin compiler - JetBrains/kotlin@f6cf434#diff-cb731b8e74d763b1baf22c9169ea3a25fccf100683163cb2fab94294bf88e197R350-R352

@Godin Godin added this to the 0.8.7 milestone Apr 5, 2021
@Godin Godin self-assigned this Apr 5, 2021
@Godin Godin added this to Implementation in Current work items via automation Apr 5, 2021
@Godin Godin added this to To Do in Filtering via automation Apr 5, 2021
@Godin Godin moved this from Implementation to Review in Current work items Apr 7, 2021
@Godin Godin marked this pull request as ready for review April 7, 2021 22:02
@Godin Godin requested a review from marchof April 7, 2021 22:02
@marchof marchof merged commit b68fe1a into master Apr 8, 2021
Filtering automation moved this from To Do to Done Apr 8, 2021
Current work items automation moved this from Review to Done Apr 8, 2021
@marchof marchof deleted the kotlin_when_string branch April 8, 2021 09:30
@marchof
Copy link
Member

marchof commented Apr 8, 2021

Nice: 150 lines of tests, 1 new line of production code 😄

Thx @Godin !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Filtering
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

2 participants