Skip to content

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 force-pushed the kotlin_when_string branch from e166379 to 02f4f3d Compare April 6, 2021 07:56
@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
@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

Archived in project
Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants