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 full-size slide

  2. multiply("hello ", 3)

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  13. // 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 full-size 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 full-size 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 full-size 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 full-size slide

  17. 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 full-size 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
    .java
    .kt
    .class

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  22. 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 full-size 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) {
    result = result + string
    }
    }

    View full-size 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
    }
    return result
    }

    View full-size slide

  25. 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 full-size 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 full-size 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;
    }
    Int?
    @Nullable Integer

    View full-size 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;
    }

    View full-size 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;
    }
    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 full-size 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 full-size 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;
    }

    View full-size 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 full-size 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 full-size slide

  34. 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 full-size slide

  35. @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 full-size slide

  36. 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 full-size slide

  37. @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 full-size 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 full-size 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 full-size slide

  40. @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 full-size 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
    }
    {
    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 full-size 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.")
    }
    "This is a cat!"

    View full-size 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
    }
    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 full-size 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() {
    Animal.
    Cat.
    fun
    abstract class Animal
    identify() {
    println("This is an animal.")
    }
    fun
    "This is an animal."

    View full-size 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
    }

    View full-size 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 full-size 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 += this
    }
    return result
    }

    View full-size 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 full-size 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 full-size 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
    }
    a += b a.plusAssign(b)
    a -= b a.minusAssign(b)

    View full-size 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 = a + b
    a = a - b
    a += b a.plusAssign(b)
    a -= b a.minusAssign(b)

    View full-size 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)
    a + b a.plus(b)
    a - b a.minus(b)

    View full-size 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
    }

    View full-size slide

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

    View full-size slide

  55. 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 full-size slide

  56. 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 full-size slide

  57. 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 full-size 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 full-size 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()
    }
    }
    package kotlin.jvm.functions
    /** A function that takes 0 arguments. */
    public interface Function0 : Function {
    /** Invokes the function. */
    public operator fun invoke(): R
    }

    View full-size 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
    }
    /** 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 full-size 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()
    }
    }

    View full-size 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 full-size 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 full-size 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 full-size slide

  65. 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 full-size slide

  66. });
    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 full-size 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 full-size 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 full-size 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;
    }
    String result = "";
    return result;

    View full-size 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;
    result += $this$multiply;

    View full-size 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 full-size 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;
    }
    final String result = "";
    return result;
    result += $this$multiply;

    View full-size 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 full-size 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;
    ""
    result
    String

    View full-size 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;
    "hi"
    result
    String

    View full-size 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
    ""
    result
    String

    View full-size 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;
    }

    View full-size 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;
    }
    public static final class ObjectRef {
    public T element;
    @Override
    public String toString() {
    return String.valueOf(element);
    }
    }

    View full-size 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;
    }

    View full-size 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;
    }
    ""
    result
    String
    ""
    result
    String

    View full-size 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
    ""
    result
    String
    element
    ObjectRef

    View full-size 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
    "hi"
    ObjectRef
    result
    String
    element

    View full-size 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;
    }

    View full-size 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;
    }
    fun example() {
    repeat(20) {
    println("Ni.")
    }
    }

    View full-size 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.")
    }
    }
    public static final void example() {
    repeat(20, (Function0) null.INSTANCE);
    }

    View full-size 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 full-size 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;
    }
    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 full-size 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 full-size 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 full-size 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) 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 full-size 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 full-size 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;
    }

    View full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  96. 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 full-size 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();
    }
    }
    fun String.multiply(times: Int): String {
    var result = ""
    repeat(times) {
    result += this
    }
    return result
    }

    View full-size slide

  98. 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 full-size slide

  99. 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 full-size 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 full-size slide

  101. 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 full-size slide

  102. 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 full-size slide

  103. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  108. 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 full-size slide

  109. 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 full-size slide

  110. 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size slide

  118. 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 full-size slide

  119. 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 full-size 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()
    }
    }
    @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 full-size 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 full-size 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 full-size 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()
    }
    }

    View full-size 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()
    }
    }
    fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }

    View full-size 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 full-size slide

  126. 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 full-size slide

  127. 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 full-size slide

  128. 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 full-size 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) {
    this.append(this)
    }

    View full-size 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 full-size 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 full-size slide

  132. 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 full-size 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 full-size slide

  134. 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 full-size slide

  135. 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 full-size 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 full-size 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 full-size 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 full-size slide

  139. 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 full-size slide

  140. 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 full-size 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);
    }
    }
    inline fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val builder = StringBuilder()
    builder.builderAction()
    return builder.toString()
    }

    View full-size slide

  142. 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 full-size slide

  143. 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 full-size 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 full-size 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()
    }
    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 full-size 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 full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  150. 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 full-size slide

  151. 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 full-size slide

  152. zsmb13
    zsmb.co/talks

    View full-size slide

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

    View full-size slide