Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dekompiling (droidcon Berlin 2019)

Dekompiling (droidcon Berlin 2019)

Kotlin has many features that are leaps and bounds ahead of Java. However, its primary target platform being the JVM, all of these features still need to compile to the same bytecode as Java does. This is a look at how a variety of interesting Kotlin features are compiled to bytecode, and what their Java equivalents would be. Even though Kotlin abstracts away much of the virtual machine and the original feature set of Java with its own features, it’s still important to know what your Kotlin code compiles to. Not only can this knowledge give you the power to optimize your code, but it will also help you avoid subtle bugs that would otherwise be near impossible to track down.

Talk recording (re-recorded after the conference): https://www.droidcon.com/media-detail?video=370862982

Marton Braun

July 03, 2019
Tweet

More Decks by Marton Braun

Other Decks in Programming

Transcript

  1. Dekompiling
    Márton Braun zsmb.co zsmb13
    [email protected]

    View Slide

  2. hello

    View Slide

  3. multiply("hello ", 3)

    View Slide

  4. fun main() {
    println( )
    }
    multiply("hello ", 3)

    View Slide

  5. "hello hello hello "
    fun main() {
    println(multiply("hello ", 3))
    }

    View Slide

  6. fun main() {
    println(multiply("hello ", 3))
    }

    View Slide

  7. fun main() {
    println(multiply("hello ", 3))
    }

    View Slide

  8. fun main() {
    println(multiply("hello ", 3))
    }

    View Slide

  9. fun main() {
    println(multiply("hello ", 3))
    }

    View Slide

  10. fun main() {
    println(multiply("hello ", 3))
    }

    View Slide

  11. fun main() {
    println(multiply("hello ", 3))
    }

    View Slide

  12. fun main() {
    println(multiply("hello ", 3))
    }

    View Slide

  13. fun main() {
    println(multiply("hello ", 3))
    }

    View Slide

  14. // access flags 0x19
    public final static main()V
    L0
    LINENUMBER 2 L0
    LDC "hello "
    ICONST_3
    INVOKESTATIC DecKt.multiply
    (Ljava/lang/String;I)Ljava/lang/String;
    ASTORE 0
    L1
    ICONST_0
    ISTORE 1
    L2
    GETSTATIC java/lang/System.out :
    Ljava/io/PrintStream;
    ALOAD 0
    INVOKEVIRTUAL java/io/PrintStream.println
    (Ljava/lang/Object;)V
    L3
    L4
    LINENUMBER 3 L4
    RETURN
    L5
    MAXSTACK = 2
    MAXLOCALS = 2
    fun main() {
    println(multiply("hello ", 3))
    }
    public final class DecKt {
    public static final void main() {
    String var0 = multiply("hello ", 3);
    boolean var1 = false;
    System.out.println(var0);
    }
    }

    View Slide

  15. // access flags 0x19
    public final static main()V
    L0
    LINENUMBER 2 L0
    LDC "hello "
    ICONST_3
    INVOKESTATIC DecKt.multiply
    (Ljava/lang/String;I)Ljava/lang/String;
    ASTORE 0
    L1
    ICONST_0
    ISTORE 1
    L2
    GETSTATIC java/lang/System.out :
    Ljava/io/PrintStream;
    ALOAD 0
    INVOKEVIRTUAL java/io/PrintStream.println
    (Ljava/lang/Object;)V
    L3
    L4
    LINENUMBER 3 L4
    RETURN
    L5
    MAXSTACK = 2
    MAXLOCALS = 2
    fun main() {
    println(multiply("hello ", 3))
    }
    public final class DecKt {
    public static final void main() {
    String var0 = multiply("hello ", 3);
    boolean var1 = false;
    System.out.println(var0);
    }
    }

    View Slide

  16. // access flags 0x19
    public final static main()V
    L0
    LINENUMBER 2 L0
    LDC "hello "
    ICONST_3
    INVOKESTATIC DecKt.multiply
    (Ljava/lang/String;I)Ljava/lang/String;
    ASTORE 0
    L1
    ICONST_0
    ISTORE 1
    L2
    GETSTATIC java/lang/System.out :
    Ljava/io/PrintStream;
    ALOAD 0
    INVOKEVIRTUAL java/io/PrintStream.println
    (Ljava/lang/Object;)V
    L3
    L4
    LINENUMBER 3 L4
    RETURN
    L5
    MAXSTACK = 2
    MAXLOCALS = 2
    fun main() {
    println(multiply("hello ", 3))
    }
    public final class DecKt {
    public static final void main() {
    String var0 = multiply("hello ", 3);
    boolean var1 = false;
    System.out.println(var0);
    }
    }

    View Slide

  17. // access flags 0x19
    public final static main()V
    L0
    LINENUMBER 2 L0
    LDC "hello "
    ICONST_3
    INVOKESTATIC DecKt.multiply
    (Ljava/lang/String;I)Ljava/lang/String;
    ASTORE 0
    L1
    ICONST_0
    ISTORE 1
    L2
    GETSTATIC java/lang/System.out :
    Ljava/io/PrintStream;
    ALOAD 0
    INVOKEVIRTUAL java/io/PrintStream.println
    (Ljava/lang/Object;)V
    L3
    L4
    LINENUMBER 3 L4
    RETURN
    L5
    MAXSTACK = 2
    MAXLOCALS = 2
    fun main() {
    println(multiply("hello ", 3))
    }
    public final class DecKt {
    public static final void main() {
    String var0 = multiply("hello ", 3);
    boolean var1 = false;
    System.out.println(var0);
    }
    }

    View Slide

  18. fun main() {
    println(multiply("hello ", 3))
    }
    public final class DecKt {
    public static final void main() {
    String var0 = multiply("hello ", 3);
    boolean var1 = false;
    System.out.println(var0);
    }
    }
    // access flags 0x19
    public final static main()V
    L0
    LINENUMBER 2 L0
    LDC "hello "
    ICONST_3
    INVOKESTATIC DecKt.multiply
    (Ljava/lang/String;I)Ljava/lang/String;
    ASTORE 0
    L1
    ICONST_0
    ISTORE 1
    L2
    GETSTATIC java/lang/System.out :
    Ljava/io/PrintStream;
    ALOAD 0
    INVOKEVIRTUAL java/io/PrintStream.println
    (Ljava/lang/Object;)V
    L3
    L4
    LINENUMBER 3 L4
    RETURN
    L5
    MAXSTACK = 2
    MAXLOCALS = 2

    View Slide

  19. fun main() {
    println(multiply("hello ", 3))
    }
    public final class DecKt {
    public static final void main() {
    String var0 = multiply("hello ", 3);
    boolean var1 = false;
    System.out.println(var0);
    }
    }
    // access flags 0x19
    public final static main()V
    L0
    LINENUMBER 2 L0
    LDC "hello "
    ICONST_3
    INVOKESTATIC DecKt.multiply
    (Ljava/lang/String;I)Ljava/lang/String;
    ASTORE 0
    L1
    ICONST_0
    ISTORE 1
    L2
    GETSTATIC java/lang/System.out :
    Ljava/io/PrintStream;
    ALOAD 0
    INVOKEVIRTUAL java/io/PrintStream.println
    (Ljava/lang/Object;)V
    L3
    L4
    LINENUMBER 3 L4
    RETURN
    L5
    MAXSTACK = 2
    MAXLOCALS = 2
    .java
    .kt
    .class

    View Slide

  20. fun main() {
    println(multiply("hello ", 3))
    }
    "hello hello hello "

    View Slide

  21. fun main() {
    println( )
    }
    multiply("hello ", 3) "hello hello hello "
    fun multiply(string: String, times: Int): String {
    }

    View Slide

  22. fun main() {
    println( )
    }
    multiply("hello ", 3) "hello hello hello "
    fun multiply(string: String, times: Int): String {
    var result = ""
    }

    View Slide

  23. fun main() {
    println( )
    }
    multiply("hello ", 3) "hello hello hello "
    fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    }
    }

    View Slide

  24. fun main() {
    println( )
    }
    multiply("hello ", 3) "hello hello hello "
    fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    }

    View Slide

  25. fun main() {
    println( )
    }
    multiply("hello ", 3) "hello hello hello "
    fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    return result
    }

    View Slide

  26. fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    return result
    }
    @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }

    View Slide

  27. fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    return result
    }
    @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }

    View Slide

  28. fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    return result
    }
    @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }
    Int?
    @Nullable Integer

    View Slide

  29. fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    return result
    }
    @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }

    View Slide

  30. fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    return result
    }
    @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }
    public class Intrinsics {
    public static void checkParameterIsNotNull(
    Object value, String paramName
    ) {
    if (value == null) {
    throwParameterIsNullException(paramName);
    }
    }
    private static void throwParameterIsNullException(
    String paramName
    ) {
    // ...
    throw new IllegalArgumentException(
    "Parameter specified as non-null is null: " +
    "method " + className + "." + methodName +
    ", parameter " + paramName);
    }
    }

    View Slide

  31. fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    return result
    }
    @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }
    public class Intrinsics {
    public static void checkParameterIsNotNull(
    Object value, String paramName
    ) {
    if (value == null) {
    throwParameterIsNullException(paramName);
    }
    }
    private static void throwParameterIsNullException(
    String paramName
    ) {
    // ...
    throw new IllegalArgumentException(
    "Parameter specified as non-null is null: " +
    "method " + className + "." + methodName +
    ", parameter " + paramName);
    }
    }

    View Slide

  32. fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    return result
    }
    @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }

    View Slide

  33. fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    return result
    }
    @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }

    View Slide

  34. fun multiply(string: String, times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + string
    }
    return result
    }
    @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }

    View Slide

  35. fun string: String,
    var result = ""
    for (i in 0 until times) {
    result = result +
    }
    return result
    }
    @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }
    times: Int): String {
    string
    multiply(

    View Slide

  36. @NotNull
    public static final String multiply(@NotNull String string, int times) {
    Intrinsics.checkParameterIsNotNull(string, "string");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + string;
    }
    return result;
    }
    fun String.
    var result = ""
    for (i in 0 until times) {
    result = result +
    }
    return result
    }
    times: Int): String {
    this
    multiply(

    View Slide

  37. fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }
    );
    @NotNull
    public static final String multiply(@NotNull String
    Intrinsics.checkParameterIsNotNull(
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result +
    }
    return result;
    }
    , int times) {
    string
    "string"
    ,
    string
    string;

    View Slide

  38. @NotNull
    public static final String multiply(@NotNull String $this$multiply, int time
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }

    View Slide

  39. @NotNull
    public static final String multiply(@NotNull String $this$multiply, int time
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }

    View Slide

  40. @NotNull
    public static final String multiply(@NotNull String $this$multiply, int time
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }

    View Slide

  41. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }

    View Slide

  42. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }
    {
    open
    }
    {
    override
    }
    class Cat : Animal()
    fun main() {
    val animal: Animal = Cat()
    animal.identify()
    }
    println("This is a cat!")
    }
    identify() {
    fun
    abstract class Animal
    identify() {
    fun
    println("This is an animal.")
    }

    View Slide

  43. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }
    {
    open
    }
    {
    override
    }
    class Cat : Animal()
    fun main() {
    val animal: Animal = Cat()
    animal.identify()
    }
    println("This is a cat!")
    }
    identify() {
    fun
    abstract class Animal
    identify() {
    fun
    println("This is an animal.")
    }
    "This is a cat!"

    View Slide

  44. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }
    class Cat : Animal()
    fun main() {
    val animal: Animal = Cat()
    animal.identify()
    }
    println("This is a cat!")
    }
    identify() {
    fun
    abstract class Animal
    identify() {
    println("This is an animal.")
    }
    fun Animal.
    Cat.

    View Slide

  45. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }
    class Cat : Animal()
    fun main() {
    val animal: Animal = Cat()
    animal.identify()
    }
    println("This is a cat!")
    }
    identify() {
    Animal.
    Cat.
    fun
    abstract class Animal
    identify() {
    println("This is an animal.")
    }
    fun
    "This is an animal."

    View Slide

  46. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }

    View Slide

  47. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result = result + this
    }
    return result
    }

    View Slide

  48. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result += this
    }
    return result
    }

    View Slide

  49. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result += this
    }
    return result
    }

    View Slide

  50. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result += this
    }
    return result
    }

    View Slide

  51. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result += this
    }
    return result
    }
    a += b a.plusAssign(b)
    a -= b a.minusAssign(b)

    View Slide

  52. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result += this
    }
    return result
    }
    a = a + b
    a = a - b
    a += b a.plusAssign(b)
    a -= b a.minusAssign(b)

    View Slide

  53. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result += this
    }
    return result
    }
    a = a + b
    a = a - b
    a += b a.plusAssign(b)
    a -= b a.minusAssign(b)
    a + b a.plus(b)
    a - b a.minus(b)

    View Slide

  54. @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    result = result + $this$multiply;
    }
    return result;
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result += this
    }
    return result
    }

    View Slide

  55. fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result += this
    }
    return result
    }

    View Slide

  56. fun repeat(times: Int, action: () -> Unit) {
    action()
    }
    for (i in 0 until times) {
    }
    fun String.multiply(times: Int): String {
    var result = ""
    for (i in 0 until times) {
    result += this
    }
    return result
    }

    View Slide

  57. fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }
    fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  58. public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var2 = 0;
    for (int var3 = times; var2 < var3; ++var2) {
    action.invoke();
    }
    }
    fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  59. public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var2 = 0;
    for (int var3 = times; var2 < var3; ++var2) {
    action.invoke();
    }
    }
    fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  60. public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var2 = 0;
    for (int var3 = times; var2 < var3; ++var2) {
    action.invoke();
    }
    }
    fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    package kotlin.jvm.functions
    /** A function that takes 0 arguments. */
    public interface Function0 : Function {
    /** Invokes the function. */
    public operator fun invoke(): R
    }

    View Slide

  61. public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var2 = 0;
    for (int var3 = times; var2 < var3; ++var2) {
    action.invoke();
    }
    }
    fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    package kotlin.jvm.functions
    /** A function that takes 0 arguments. */
    public interface Function0 : Function {
    /** Invokes the function. */
    public operator fun invoke(): R
    }
    /** A function that takes 1 argument. */
    public interface Function1 : Function {
    /** Invokes the function with the specified argument. */
    public operator fun invoke(p1: P1): R
    }

    View Slide

  62. public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var2 = 0;
    for (int var3 = times; var2 < var3; ++var2) {
    action.invoke();
    }
    }
    fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  63. public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var2 = 0;
    for (int var3 = times; var2 < var3; ++var2) {
    action.invoke();
    }
    }
    fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  64. public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var2 = 0;
    for (int var3 = times; var2 < var3; ++var2) {
    action.invoke();
    }
    }
    fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  65. public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var2 = 0;
    for (int var3 = times; var2 < var3; ++var2) {
    action.invoke();
    }
    }
    fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  66. fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }
    public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var2 = 0;
    for (int var3 = times; var2 < var3; ++var2) {
    action.invoke();
    }
    }

    View Slide

  67. });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }

    View Slide

  68. });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }

    View Slide

  69. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }

    View Slide

  70. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    String result = "";
    return result;

    View Slide

  71. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    String result = "";
    return result;
    result += $this$multiply;

    View Slide

  72. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    String result = "";
    return result;
    result += $this$multiply;

    View Slide

  73. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    final String result = "";
    return result;
    result += $this$multiply;

    View Slide

  74. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    final String result = "";
    return result;
    result += $this$multiply;

    View Slide

  75. });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    final String result = "";
    return result;
    result += $this$multiply;
    ""
    result
    String

    View Slide

  76. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    final String result = "";
    return result;
    result += $this$multiply;
    "hi"
    result
    String

    View Slide

  77. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    final String result = "";
    return result;
    result += $this$multiply;
    "hi"
    result
    String
    ""
    result
    String

    View Slide

  78. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }

    View Slide

  79. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    public static final class ObjectRef {
    public T element;
    @Override
    public String toString() {
    return String.valueOf(element);
    }
    }

    View Slide

  80. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }

    View Slide

  81. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    ""
    result
    String
    ""
    result
    String

    View Slide

  82. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    ""
    result
    String
    ""
    result
    String
    ""
    result
    String
    element
    ObjectRef

    View Slide

  83. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    ""
    result
    String
    ""
    result
    String
    "hi"
    ObjectRef
    result
    String
    element

    View Slide

  84. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }

    View Slide

  85. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    fun example() {
    repeat(20) {
    println("Ni.")
    }
    }

    View Slide

  86. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    fun example() {
    repeat(20) {
    println("Ni.")
    }
    }
    public static final void example() {
    repeat(20, (Function0) null.INSTANCE);
    }

    View Slide

  87. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    fun example() {
    repeat(20) {
    println("Ni.")
    }
    }
    public static final void example() {
    repeat(20, (Function0) null.INSTANCE);
    }

    View Slide

  88. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    public static final void example() {
    repeat(20, (Function0) null.INSTANCE);
    }
    final class NiKt$example$1 implements Function0 {
    public static final NiKt$example$1 INSTANCE =
    new NiKt$example$1();
    public final void invoke() {
    String str = "Ni.";
    System.out.println(str);
    }
    }

    View Slide

  89. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    public static final void example() {
    repeat(20, (Function0) null.INSTANCE);
    }
    final class NiKt$example$1 implements Function0 {
    public static final NiKt$example$1 INSTANCE =
    new NiKt$example$1();
    public final void invoke() {
    String str = "Ni.";
    System.out.println(str);
    }
    }

    View Slide

  90. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    public static final void example() {
    repeat(20, (Function0) null.INSTANCE);
    }
    final class NiKt$example$1 implements Function0 {
    public static final NiKt$example$1 INSTANCE =
    new NiKt$example$1();
    public final void invoke() {
    String str = "Ni.";
    System.out.println(str);
    }
    }

    View Slide

  91. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    public static final void example() {
    repeat(20, (Function0) NiKt$example$1.INSTANCE);
    }
    final class NiKt$example$1 implements Function0 {
    public static final NiKt$example$1 INSTANCE =
    new NiKt$example$1();
    public final void invoke() {
    String str = "Ni.";
    System.out.println(str);
    }
    }

    View Slide

  92. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }
    public static final void example() {
    repeat(20, (Function0) NiKt$example$1.INSTANCE);
    }
    final class NiKt$example$1 implements Function0 {
    public static final NiKt$example$1 INSTANCE =
    new NiKt$example$1();
    public final void invoke() {
    String str = "Ni.";
    System.out.println(str);
    }
    }

    View Slide

  93. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }

    View Slide

  94. // ...
    });
    return (String) result.element;
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    final ObjectRef result = new ObjectRef();
    result.element = "";
    repeat(times, new Function0() {
    public final void invoke() {
    ObjectRef var10000 = result;
    String var10001 = (String) var10000.element;
    var10000.element = var10001 + $this$multiply;
    }

    View Slide

  95. fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  96. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  97. public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    action.invoke();
    }
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  98. public static final void repeat(int times, @NotNull Function0 action) {
    Intrinsics.checkParameterIsNotNull(action, "action");
    int var3 = 0;
    for (int var4 = times; var3 < var4; ++var3) {
    action.invoke();
    }
    }
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  99. fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }
    @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    String result = "";
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    result = result + $this$multiply;
    }
    return result;
    }

    View Slide

  100. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  101. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  102. inline fun repeat( , action: () -> Unit) {
    for (i in 0 until ) {
    action()
    }
    }
    fun String.multiply(times: Int): String {
    var result = ""
    repeat( ) {
    result += this
    }
    return result
    }
    times
    times
    times: Int

    View Slide

  103. inline fun repeat( , action: () -> Unit) {
    for (i in 0 until ) {
    action()
    }
    }
    times
    fun String.multiply(times: Int): String {
    var result = ""
    repeat( ) {
    result += this
    }
    return result
    }

    View Slide

  104. inline fun repeat( , ) {
    for (i in 0 until ) {
    }
    }
    times
    fun String.multiply(times: Int): String {
    var result = ""
    repeat( )
    return result
    }
    action
    action: () -> Unit
    }
    {
    result += this
    ()

    View Slide

  105. inline fun repeat( , ) {
    for (i in 0 until ) {
    }
    }
    ()
    fun String.multiply(times: Int): String {
    var result = ""
    repeat( )
    return result
    }
    { result += this }
    times

    View Slide

  106. inline fun repeat( , ) {
    }
    for (i in 0 until times) {
    result += this
    }
    fun String.multiply(times: Int): String {
    var result = ""
    return result
    }
    repeat( )

    View Slide

  107. for (i in 0 until times) {
    result += this
    }
    fun String.multiply(times: Int): String {
    var result = ""
    return result
    }
    repeat( )

    View Slide

  108. fun String.multiply(times: Int): String {
    var result = ""
    return result
    }
    for (i in 0 until times) {
    result += this
    }

    View Slide

  109. fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  110. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  111. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    ALOAD 2
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder. ()V
    SWAP
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    ALOAD 0
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()
    Ljava/lang/String;
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  112. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    ALOAD 2
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder. ()V
    SWAP
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    ALOAD 0
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()
    Ljava/lang/String;
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  113. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    ALOAD 2
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder. ()V
    SWAP
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    ALOAD 0
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()
    Ljava/lang/String;
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  114. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    ALOAD 2
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder. ()V
    SWAP
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    ALOAD 0
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()
    Ljava/lang/String;
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  115. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    ALOAD 2
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder. ()V
    SWAP
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    ALOAD 0
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()
    Ljava/lang/String;
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  116. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    ALOAD 2
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder. ()V
    SWAP
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    ALOAD 0
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()
    Ljava/lang/String;
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  117. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    ALOAD 2
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder. ()V
    SWAP
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    ALOAD 0
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()
    Ljava/lang/String;
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  118. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    ALOAD 2
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder. ()V
    SWAP
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    ALOAD 0
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)
    Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()
    Ljava/lang/String;
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View Slide

  119. fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  120. fun String.multiply(times: Int): String {
    val builder = StringBuilder()
    repeat(times) {
    builder.append(this)
    }
    return builder.toString()
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  121. fun String.multiply(times: Int): String {
    val builder = StringBuilder()
    repeat(times) {
    builder.append(this)
    }
    return builder.toString()
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    StringBuilder builder = new StringBuilder();
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    builder.append($this$multiply);
    }
    String var100 = builder.toString();
    Intrinsics.checkExpressionValueIsNotNull(var100, "builder.toString()");
    return var100;
    }

    View Slide

  122. fun String.multiply(times: Int): String {
    val builder = StringBuilder()
    repeat(times) {
    builder.append(this)
    }
    return builder.toString()
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    StringBuilder builder = new StringBuilder();
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    builder.append($this$multiply);
    }
    String var100 = builder.toString();
    Intrinsics.checkExpressionValueIsNotNull(var100, "builder.toString()");
    return var100;
    }

    View Slide

  123. fun String.multiply(times: Int): String {
    val builder = StringBuilder()
    repeat(times) {
    builder.append(this)
    }
    return builder.toString()
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    @NotNull public static final
    String multiply(@NotNull String $this$multiply, int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    StringBuilder builder = new StringBuilder();
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    builder.append($this$multiply);
    }
    String var100 = builder.toString();
    Intrinsics.checkExpressionValueIsNotNull(var100, "builder.toString()");
    return var100;
    }

    View Slide

  124. fun String.multiply(times: Int): String {
    val builder = StringBuilder()
    repeat(times) {
    builder.append(this)
    }
    return builder.toString()
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }

    View Slide

  125. fun String.multiply(times: Int): String {
    val builder = StringBuilder()
    repeat(times) {
    builder.append(this)
    }
    return builder.toString()
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }

    View Slide

  126. fun String.multiply(times: Int): String {
    val builder = StringBuilder()
    repeat(times) {
    builder.append(this)
    }
    return builder.toString()
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }

    View Slide

  127. fun String.multiply(times: Int): String {
    val builder = StringBuilder()
    repeat(times) {
    builder.append(this)
    }
    return builder.toString()
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }

    View Slide

  128. fun String.multiply(times: Int): String {
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    repeat(times) {
    append(this)
    }
    }
    return buildString {

    View Slide

  129. fun String.multiply(times: Int): String {
    return buildString {
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    repeat(times) {
    append(this)
    }

    View Slide

  130. fun String.multiply(times: Int): String {
    return buildString {
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    repeat(times) {
    this.append(this)
    }

    View Slide

  131. fun String.multiply(times: Int): String {
    return buildString {
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    repeat(times) {
    this.append(this)
    }

    View Slide

  132. fun String.multiply(times: Int): String {
    return buildString {
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    repeat(times) {
    this.append(this)
    }

    View Slide

  133. fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    }
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    append(this@multiply)
    this.

    View Slide

  134. fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    }
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    append(this@multiply)
    this.

    View Slide

  135. fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    }
    }
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    append(this@multiply)
    this.

    View Slide

  136. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, final int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    return buildString(new Function1() {
    public void invoke(@NotNull StringBuilder $this$buildString) {
    Intrinsics.checkParameterIsNotNull($this$buildString, "...");
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    $this$buildString.append($this$multiply);
    }
    }
    });
    }

    View Slide

  137. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, final int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    return buildString(new Function1() {
    public void invoke(@NotNull StringBuilder $this$buildString) {
    Intrinsics.checkParameterIsNotNull($this$buildString, "...");
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    $this$buildString.append($this$multiply);
    }
    }
    });
    }

    View Slide

  138. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, final int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    return buildString(new Function1() {
    public void invoke(@NotNull StringBuilder $this$buildString) {
    Intrinsics.checkParameterIsNotNull($this$buildString, "...");
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    $this$buildString.append($this$multiply);
    }
    }
    });
    }

    View Slide

  139. inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, final int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    return buildString(new Function1() {
    public void invoke(@NotNull StringBuilder $this$buildString) {
    Intrinsics.checkParameterIsNotNull($this$buildString, "...");
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    $this$buildString.append($this$multiply);
    }
    }
    });
    }

    View Slide

  140. fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }
    return buildString(new Function1() {
    public void invoke(@NotNull StringBuilder $this$buildString) {
    Intrinsics.checkParameterIsNotNull($this$buildString, "...");
    }
    });
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    $this$buildString.append($this$multiply);
    }
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, final int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    }

    View Slide

  141. return buildString(new Function1() {
    public void invoke(@NotNull StringBuilder $this$buildString) {
    Intrinsics.checkParameterIsNotNull($this$buildString, "...");
    }
    });
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, final int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    $this$buildString.append($this$multiply);
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }

    View Slide

  142. return buildString(new Function1() {
    public void invoke(@NotNull StringBuilder $this$buildString) {
    Intrinsics.checkParameterIsNotNull($this$buildString, "...");
    }
    });
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, final int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    $this$buildString.append($this$multiply);
    }
    }
    inline fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }

    View Slide

  143. inline fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    StringBuilder $this$buildString = new StringBuilder();
    String var10000 = $this$buildString.toString();
    Intrinsics.checkExpressionValueIsNotNull(var10000, "...");
    return var10000;
    @NotNull public static final
    String multiply(@NotNull final String $this$multiply, final int times) {
    Intrinsics.checkParameterIsNotNull($this$multiply, "$this$multiply");
    int var4 = 0;
    for (int var5 = times; var4 < var5; ++var4) {
    $this$buildString.append($this$multiply);
    }
    }

    View Slide

  144. fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    inline fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }

    View Slide

  145. fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    inline fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }

    View Slide

  146. fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    inline fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    package kotlin.text
    @kotlin.internal.InlineOnly
    public inline fun buildString(
    builderAction: StringBuilder.() -> Unit
    ): String = StringBuilder().apply(builderAction).toString()
    package kotlin
    @kotlin.internal.InlineOnly
    public inline fun repeat(times: Int, action: (Int) -> Unit) {
    contract { callsInPlace(action) }
    for (index in 0 until times) {
    action(index)
    }
    }

    View Slide

  147. fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    inline fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    package kotlin.text
    @kotlin.internal.InlineOnly
    public inline fun buildString(
    builderAction: StringBuilder.() -> Unit
    ): String = StringBuilder().apply(builderAction).toString()
    package kotlin
    @kotlin.internal.InlineOnly
    public inline fun repeat(times: Int, action: (Int) -> Unit) {
    contract { callsInPlace(action) }
    for (index in 0 until times) {
    action(index)
    }
    }

    View Slide

  148. fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }
    inline fun repeat(times: Int, action: () -> Unit) {
    for (i in 0 until times) {
    action()
    }
    }
    inline fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }
    package kotlin.text
    @kotlin.internal.InlineOnly
    public inline fun buildString(
    builderAction: StringBuilder.() -> Unit
    ): String = StringBuilder().apply(builderAction).toString()
    package kotlin
    @kotlin.internal.InlineOnly
    public inline fun repeat(times: Int, action: (Int) -> Unit) {
    contract { callsInPlace(action) }
    for (index in 0 until times) {
    action(index)
    }
    }

    View Slide

  149. fun String.multiply(times: Int): String {
    return buildString {
    repeat(times) {
    append(this@multiply)
    }
    }
    }

    View Slide

  150. fun String.multiply(times: Int): String {
    return buildString(capacity = length * times) {
    repeat(times) {
    append(this@multiply)
    }
    }
    }

    View Slide

  151. Related talks
    • Kotlin: Uncovered
     Victoria Gonda, Chicago Roboto 2017
     https://vimeo.com/217569130
    • Desugaring Kotlin features and their performance impact
     Ionuț Baloșin, VoxxedDays Bucharest 2019
     https://www.youtube.com/watch?v=D2a2vK-mfp4
    • Kotlin Under the Hood
     Chet Haase & Romain Guy, I/O ’19
     https://www.youtube.com/watch?v=Ta5wBJsC39s

    View Slide

  152. References
    • Execution in the Kingdom of Nouns
     https://steve-yegge.blogspot.com/2006/03/execution-in-
    kingdom-of-nouns.html
    • Kotlin 1.3 changes to functional types
     https://kotlinlang.org/docs/reference/whatsnew13.html#functio
    ns-with-big-arity

    View Slide

  153. zsmb13
    zsmb.co/talks

    View Slide

  154. Questions?
    Márton Braun zsmb.co zsmb13
    [email protected]

    View Slide