Optymalizacja funkcji wyższego rzędu

Gdy już wiemy, czym są funkcje wyższego rzędu w Kotlinie, to możemy zadać pytanie – z wydajnością?

Cóż… JVM ma swoje ograniczenia i był projektowany z myślą o programowaniu obiektowym. Jednak natura funkcyjna powoduje, że mamy dużą ilość obiektów pośredniczących. Każda funkcja to osobny obiekt skojarzony z klasą, która jest reprezentowana jako inny obiekt. Coś, co ma sens w przypadku programowania obiektowego, gdzie poszczególne warstwy dostarczają części funkcjonalności tu, kończy się „nadprodukcją” stosu (dołóżmy jeszcze do tego dużo konstrukcji invoke virtual).

Twórcy języka Kotlin mając świadomość tego problemu postanowili wbudować w język mechanizm zwany inliningiem.

Problem

Przyjrzyjmy się poniższemu programowi:

Listing 1. „Klasyczne” wykorzystanie wyrażenia lambda jako HOF

fun main(args: Array<String>) {

    timingLog(1, 2, { a, b -> a + b })

}

fun <T, U, R> timingLog(a: T, b: U, f: (T, U) -> R): R {
    val watch = Stopwatch.createStarted()
    try {
        return f(a, b)
    }finally{
        println("call in ns: "  + watch.elapsed(TimeUnit.NANOSECONDS))
    }
}

Mamy tu funkcję, która jako parametr przyjmuje inną funkcję i jej wywołanie obudowuje logowaniem czasu wykonania (PoC, bo tego się tak nie robi). Cała „magia” dzieje się w funkcji timingLog. Wprowadźmy słowo kluczowe inline:

Listing 2. Wywołanie funkcji inline

fun main(args: Array<String>) {

    timingLog(1, 2, { a, b -> a + b })

}

inline fun <T, U, R> timingLog(a: T, b: U, f: (T, U) -> R): R {
    val watch = Stopwatch.createStarted()
    try {
        return f(a, b)
    }finally{
        println("call in ns: "  + watch.elapsed(TimeUnit.NANOSECONDS))
    }
}

Z punktu widzenia kodu nic tu się nie zmieniło. Ot dodaliśmy słówko, które tylko „zaśmieca” kod. W rzeczywistości inline powoduje, że kompilator przenosi kod funkcji timingLog oraz przekazanej jej lambdy w miejsce wywołania tej pierwszej.

Prawda kodu, a prawda bytecodu

Co oznacza „przenosi”? Rzućmy okiem na bytecode wygenerowany dla pierwszego przypadku:

Listing 3. bytecode pierwszego przypadku

Classfile /home/koziolek/workspace/oldone/blog_old/target/classes/pl/koziolekweb/blog/inlines/InlinesKt.class
  Last modified 2016-05-23; size 2658 bytes
  MD5 checksum d770a2c85d4400192ea83e0c72e4bd84
  Compiled from "Inlines.kt"
public final class pl.koziolekweb.blog.inlines.InlinesKt
  minor version: 0
  major version: 50
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
Constant pool:
    #1 = Utf8               pl/koziolekweb/blog/inlines/InlinesKt
    #2 = Class              #1            // pl/koziolekweb/blog/inlines/InlinesKt
    #3 = Utf8               java/lang/Object
    #4 = Class              #3            // java/lang/Object
    #5 = Utf8               main
    #6 = Utf8               ([Ljava/lang/String;)V
    #7 = Utf8               Lorg/jetbrains/annotations/NotNull;
    #8 = Utf8               args
    #9 = String             #8            // args
   #10 = Utf8               kotlin/jvm/internal/Intrinsics
   #11 = Class              #10           // kotlin/jvm/internal/Intrinsics
   #12 = Utf8               checkParameterIsNotNull
   #13 = Utf8               (Ljava/lang/Object;Ljava/lang/String;)V
   #14 = NameAndType        #12:#13       // checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
   #15 = Methodref          #11.#14       // kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
   #16 = Utf8               java/lang/Integer
   #17 = Class              #16           // java/lang/Integer
   #18 = Utf8               valueOf
   #19 = Utf8               (I)Ljava/lang/Integer;
   #20 = NameAndType        #18:#19       // valueOf:(I)Ljava/lang/Integer;
   #21 = Methodref          #17.#20       // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #22 = Utf8               pl/koziolekweb/blog/inlines/InlinesKt$main$1
   #23 = Class              #22           // pl/koziolekweb/blog/inlines/InlinesKt$main$1
   #24 = Utf8               INSTANCE
   #25 = Utf8               Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
   #26 = NameAndType        #24:#25       // INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
   #27 = Fieldref           #23.#26       // pl/koziolekweb/blog/inlines/InlinesKt$main$1.INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
   #28 = Utf8               kotlin/jvm/functions/Function2
   #29 = Class              #28           // kotlin/jvm/functions/Function2
   #30 = Utf8               timingLog
   #31 = Utf8               (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
   #32 = NameAndType        #30:#31       // timingLog:(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
   #33 = Methodref          #2.#32        // pl/koziolekweb/blog/inlines/InlinesKt.timingLog:(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
   #34 = Utf8               [Ljava/lang/String;
   #35 = Utf8               f
   #36 = String             #35           // f
   #37 = Utf8               com/google/common/base/Stopwatch
   #38 = Class              #37           // com/google/common/base/Stopwatch
   #39 = Utf8               createStarted
   #40 = Utf8               ()Lcom/google/common/base/Stopwatch;
   #41 = NameAndType        #39:#40       // createStarted:()Lcom/google/common/base/Stopwatch;
   #42 = Methodref          #38.#41       // com/google/common/base/Stopwatch.createStarted:()Lcom/google/common/base/Stopwatch;
   #43 = Utf8               invoke
   #44 = Utf8               (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   #45 = NameAndType        #43:#44       // invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   #46 = InterfaceMethodref #29.#45       // kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   #47 = Utf8               java/lang/StringBuilder
   #48 = Class              #47           // java/lang/StringBuilder
   #49 = Utf8               <init>
   #50 = Utf8               ()V
   #51 = NameAndType        #49:#50       // "<init>":()V
   #52 = Methodref          #48.#51       // java/lang/StringBuilder."<init>":()V
   #53 = Utf8               call in ns:
   #54 = String             #53           // call in ns:
   #55 = Utf8               append
   #56 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
   #57 = NameAndType        #55:#56       // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #58 = Methodref          #48.#57       // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #59 = Utf8               java/util/concurrent/TimeUnit
   #60 = Class              #59           // java/util/concurrent/TimeUnit
   #61 = Utf8               NANOSECONDS
   #62 = Utf8               Ljava/util/concurrent/TimeUnit;
   #63 = NameAndType        #61:#62       // NANOSECONDS:Ljava/util/concurrent/TimeUnit;
   #64 = Fieldref           #60.#63       // java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
   #65 = Utf8               elapsed
   #66 = Utf8               (Ljava/util/concurrent/TimeUnit;)J
   #67 = NameAndType        #65:#66       // elapsed:(Ljava/util/concurrent/TimeUnit;)J
   #68 = Methodref          #38.#67       // com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
   #69 = Utf8               (J)Ljava/lang/StringBuilder;
   #70 = NameAndType        #55:#69       // append:(J)Ljava/lang/StringBuilder;
   #71 = Methodref          #48.#70       // java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
   #72 = Utf8               toString
   #73 = Utf8               ()Ljava/lang/String;
   #74 = NameAndType        #72:#73       // toString:()Ljava/lang/String;
   #75 = Methodref          #48.#74       // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #76 = Utf8               java/lang/System
   #77 = Class              #76           // java/lang/System
   #78 = Utf8               out
   #79 = Utf8               Ljava/io/PrintStream;
   #80 = NameAndType        #78:#79       // out:Ljava/io/PrintStream;
   #81 = Fieldref           #77.#80       // java/lang/System.out:Ljava/io/PrintStream;
   #82 = Utf8               java/io/PrintStream
   #83 = Class              #82           // java/io/PrintStream
   #84 = Utf8               println
   #85 = Utf8               (Ljava/lang/Object;)V
   #86 = NameAndType        #84:#85       // println:(Ljava/lang/Object;)V
   #87 = Methodref          #83.#86       // java/io/PrintStream.println:(Ljava/lang/Object;)V
   #88 = Utf8               watch
   #89 = Utf8               Lcom/google/common/base/Stopwatch;
   #90 = Utf8               a
   #91 = Utf8               Ljava/lang/Object;
   #92 = Utf8               b
   #93 = Utf8               Lkotlin/jvm/functions/Function2;
   #94 = Utf8               java/lang/Throwable
   #95 = Class              #94           // java/lang/Throwable
   #96 = Utf8               Lkotlin/Metadata;
   #97 = Utf8               mv
   #98 = Integer            1
   #99 = Utf8               bv
  #100 = Integer            0
  #101 = Utf8               k
  #102 = Integer            2
  #103 = Utf8               d1
  #104 = Utf8                \n \n\n \n\n\n\n\n 0200¢GH\" \"\t\"2\nH2H\t2HH\tH0\r¢¨
  #105 = Utf8               d2
  #106 = Utf8
  #107 = Utf8               R
  #108 = Utf8               T
  #109 = Utf8               U
  #110 = Utf8               Lkotlin/Function2;
  #111 = Utf8               blog
  #112 = Utf8               Inlines.kt
  #113 = Utf8               Code
  #114 = Utf8               LocalVariableTable
  #115 = Utf8               LineNumberTable
  #116 = Utf8               RuntimeInvisibleParameterAnnotations
  #117 = Utf8               StackMapTable
  #118 = Utf8               Signature
  #119 = Utf8               <T:Ljava/lang/Object;U:Ljava/lang/Object;R:Ljava/lang/Object;>(TT;TU;Lkotlin/jvm/functions/Function2<-TT;-TU;+TR;>;)TR;
  #120 = Utf8               SourceFile
  #121 = Utf8               SourceDebugExtension
  #122 = Utf8               InnerClasses
  #123 = Utf8               RuntimeVisibleAnnotations
{
  public static final void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0
         1: ldc           #9                  // String args
         3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
         6: iconst_1
         7: invokestatic  #21                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        10: iconst_2
        11: invokestatic  #21                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        14: getstatic     #27                 // Field pl/koziolekweb/blog/inlines/InlinesKt$main$1.INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
        17: checkcast     #29                 // class kotlin/jvm/functions/Function2
        20: invokestatic  #33                 // Method timingLog:(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
        23: pop
        24: return
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      25     0  args   [Ljava/lang/String;
      LineNumberTable:
        line 14: 6
        line 16: 24
    RuntimeInvisibleParameterAnnotations:
      0:
        0: #7()

  public static final <T extends java.lang.Object, U extends java.lang.Object, R extends java.lang.Object> R timingLog(T, U, kotlin.jvm.functions.Function2<? super T, ? super U, ? extends R>);
    descriptor: (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    Code:
      stack=3, locals=6, args_size=3
         0: aload_2
         1: ldc           #36                 // String f
         3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
         6: invokestatic  #42                 // Method com/google/common/base/Stopwatch.createStarted:()Lcom/google/common/base/Stopwatch;
         9: astore_3
        10: nop
        11: aload_2
        12: aload_0
        13: aload_1
        14: invokeinterface #46,  3           // InterfaceMethod kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
        19: astore        4
        21: new           #48                 // class java/lang/StringBuilder
        24: dup
        25: invokespecial #52                 // Method java/lang/StringBuilder."<init>":()V
        28: ldc           #54                 // String call in ns:
        30: invokevirtual #58                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        33: aload_3
        34: getstatic     #64                 // Field java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
        37: invokevirtual #68                 // Method com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
        40: invokevirtual #71                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        43: invokevirtual #75                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        46: astore        5
        48: nop
        49: getstatic     #81                 // Field java/lang/System.out:Ljava/io/PrintStream;
        52: aload         5
        54: invokevirtual #87                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        57: aload         4
        59: areturn
        60: astore        4
        62: new           #48                 // class java/lang/StringBuilder
        65: dup
        66: invokespecial #52                 // Method java/lang/StringBuilder."<init>":()V
        69: ldc           #54                 // String call in ns:
        71: invokevirtual #58                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        74: aload_3
        75: getstatic     #64                 // Field java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
        78: invokevirtual #68                 // Method com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
        81: invokevirtual #71                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        84: invokevirtual #75                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        87: astore        5
        89: nop
        90: getstatic     #81                 // Field java/lang/System.out:Ljava/io/PrintStream;
        93: aload         5
        95: invokevirtual #87                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        98: aload         4
       100: athrow
      Exception table:
         from    to  target type
            10    21    60   any
            60    62    60   any
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           10      91     3 watch   Lcom/google/common/base/Stopwatch;
            0     101     0     a   Ljava/lang/Object;
            0     101     1     b   Ljava/lang/Object;
            0     101     2     f   Lkotlin/jvm/functions/Function2;
      LineNumberTable:
        line 19: 6
        line 20: 10
        line 21: 11
        line 23: 21
        line 23: 60
        line 23: 62
      StackMapTable: number_of_entries = 1
        frame_type = 255 /* full_frame */
          offset_delta = 60
          locals = [ class java/lang/Object, class java/lang/Object, class kotlin/jvm/functions/Function2, class com/google/common/base/Stopwatch ]
          stack = [ class java/lang/Throwable ]
    Signature: #119                         // <T:Ljava/lang/Object;U:Ljava/lang/Object;R:Ljava/lang/Object;>(TT;TU;Lkotlin/jvm/functions/Function2<-TT;-TU;+TR;>;)TR;
    RuntimeInvisibleParameterAnnotations:
      0:
      1:
      2:
        0: #7()
}
SourceFile: "Inlines.kt"
SourceDebugExtension:
  SMAP
  Inlines.kt
  Kotlin
  *S Kotlin
  *F
  + 1 Inlines.kt
  pl/koziolekweb/blog/inlines/InlinesKt
  *L
  1#1,25:1
  *E
InnerClasses:
     static final #23; //class pl/koziolekweb/blog/inlines/InlinesKt$main$1
RuntimeVisibleAnnotations:
  0: #96(#97=[I#98,I#98,I#98],#99=[I#98,I#100,I#100],#101=I#102,#103=[s#104],#105=[s#5,s#106,s#8,s#106,s#106,s#6,s#30,s#107,s#108,s#109,s#90,s#92,s#35,s#110,s#31,s#111])

Oraz to samo dla drugiego przypadku:

Listing 4. Wpływ inline na bytecode

Classfile /home/koziolek/workspace/oldone/blog_old/target/classes/pl/koziolekweb/blog/inlines/InlinesKt.class
  Last modified 2016-05-23; size 2890 bytes
  MD5 checksum 75e883aed086b2f08d1b37244b23de8c
  Compiled from "Inlines.kt"
public final class pl.koziolekweb.blog.inlines.InlinesKt
  minor version: 0
  major version: 50
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
Constant pool:
    #1 = Utf8               pl/koziolekweb/blog/inlines/InlinesKt
    #2 = Class              #1            // pl/koziolekweb/blog/inlines/InlinesKt
    #3 = Utf8               java/lang/Object
    #4 = Class              #3            // java/lang/Object
    #5 = Utf8               main
    #6 = Utf8               ([Ljava/lang/String;)V
    #7 = Utf8               Lorg/jetbrains/annotations/NotNull;
    #8 = Utf8               args
    #9 = String             #8            // args
   #10 = Utf8               kotlin/jvm/internal/Intrinsics
   #11 = Class              #10           // kotlin/jvm/internal/Intrinsics
   #12 = Utf8               checkParameterIsNotNull
   #13 = Utf8               (Ljava/lang/Object;Ljava/lang/String;)V
   #14 = NameAndType        #12:#13       // checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
   #15 = Methodref          #11.#14       // kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
   #16 = Utf8               com/google/common/base/Stopwatch
   #17 = Class              #16           // com/google/common/base/Stopwatch
   #18 = Utf8               createStarted
   #19 = Utf8               ()Lcom/google/common/base/Stopwatch;
   #20 = NameAndType        #18:#19       // createStarted:()Lcom/google/common/base/Stopwatch;
   #21 = Methodref          #17.#20       // com/google/common/base/Stopwatch.createStarted:()Lcom/google/common/base/Stopwatch;
   #22 = Utf8               java/lang/StringBuilder
   #23 = Class              #22           // java/lang/StringBuilder
   #24 = Utf8               <init>
   #25 = Utf8               ()V
   #26 = NameAndType        #24:#25       // "<init>":()V
   #27 = Methodref          #23.#26       // java/lang/StringBuilder."<init>":()V
   #28 = Utf8               call in ns:
   #29 = String             #28           // call in ns:
   #30 = Utf8               append
   #31 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
   #32 = NameAndType        #30:#31       // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #33 = Methodref          #23.#32       // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #34 = Utf8               java/util/concurrent/TimeUnit
   #35 = Class              #34           // java/util/concurrent/TimeUnit
   #36 = Utf8               NANOSECONDS
   #37 = Utf8               Ljava/util/concurrent/TimeUnit;
   #38 = NameAndType        #36:#37       // NANOSECONDS:Ljava/util/concurrent/TimeUnit;
   #39 = Fieldref           #35.#38       // java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
   #40 = Utf8               elapsed
   #41 = Utf8               (Ljava/util/concurrent/TimeUnit;)J
   #42 = NameAndType        #40:#41       // elapsed:(Ljava/util/concurrent/TimeUnit;)J
   #43 = Methodref          #17.#42       // com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
   #44 = Utf8               (J)Ljava/lang/StringBuilder;
   #45 = NameAndType        #30:#44       // append:(J)Ljava/lang/StringBuilder;
   #46 = Methodref          #23.#45       // java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
   #47 = Utf8               toString
   #48 = Utf8               ()Ljava/lang/String;
   #49 = NameAndType        #47:#48       // toString:()Ljava/lang/String;
   #50 = Methodref          #23.#49       // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #51 = Utf8               java/lang/System
   #52 = Class              #51           // java/lang/System
   #53 = Utf8               out
   #54 = Utf8               Ljava/io/PrintStream;
   #55 = NameAndType        #53:#54       // out:Ljava/io/PrintStream;
   #56 = Fieldref           #52.#55       // java/lang/System.out:Ljava/io/PrintStream;
   #57 = Utf8               java/io/PrintStream
   #58 = Class              #57           // java/io/PrintStream
   #59 = Utf8               println
   #60 = Utf8               (Ljava/lang/Object;)V
   #61 = NameAndType        #59:#60       // println:(Ljava/lang/Object;)V
   #62 = Methodref          #58.#61       // java/io/PrintStream.println:(Ljava/lang/Object;)V
   #63 = Utf8               a
   #64 = Utf8               I
   #65 = Utf8               b
   #66 = Utf8               $i$a$1$timingLog
   #67 = Utf8               watch$iv
   #68 = Utf8               Lcom/google/common/base/Stopwatch;
   #69 = Utf8               a$iv
   #70 = Utf8               b$iv
   #71 = Utf8               $i$f$timingLog
   #72 = Utf8               [Ljava/lang/String;
   #73 = Class              #72           // "[Ljava/lang/String;"
   #74 = Utf8               java/lang/Throwable
   #75 = Class              #74           // java/lang/Throwable
   #76 = Utf8               java/lang/String
   #77 = Class              #76           // java/lang/String
   #78 = Utf8               timingLog
   #79 = Utf8               (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
   #80 = Utf8               f
   #81 = String             #80           // f
   #82 = Utf8               kotlin/jvm/functions/Function2
   #83 = Class              #82           // kotlin/jvm/functions/Function2
   #84 = Utf8               invoke
   #85 = Utf8               (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   #86 = NameAndType        #84:#85       // invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   #87 = InterfaceMethodref #83.#86       // kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   #88 = Utf8               kotlin/jvm/internal/InlineMarker
   #89 = Class              #88           // kotlin/jvm/internal/InlineMarker
   #90 = Utf8               finallyStart
   #91 = Utf8               (I)V
   #92 = NameAndType        #90:#91       // finallyStart:(I)V
   #93 = Methodref          #89.#92       // kotlin/jvm/internal/InlineMarker.finallyStart:(I)V
   #94 = Utf8               finallyEnd
   #95 = NameAndType        #94:#91       // finallyEnd:(I)V
   #96 = Methodref          #89.#95       // kotlin/jvm/internal/InlineMarker.finallyEnd:(I)V
   #97 = Utf8               watch
   #98 = Utf8               Ljava/lang/Object;
   #99 = Utf8               Lkotlin/jvm/functions/Function2;
  #100 = Utf8               Lkotlin/Metadata;
  #101 = Utf8               mv
  #102 = Integer            1
  #103 = Utf8               bv
  #104 = Integer            0
  #105 = Utf8               k
  #106 = Integer            2
  #107 = Utf8               d1
  #108 = Utf8                \n \n\n \n\n\n\n\n 0200¢JH\" \"\t\"2\nH2H\t2HH\tH0\rH†¢¨
  #109 = Utf8               d2
  #110 = Utf8
  #111 = Utf8               R
  #112 = Utf8               T
  #113 = Utf8               U
  #114 = Utf8               Lkotlin/Function2;
  #115 = Utf8               blog
  #116 = Utf8               Inlines.kt
  #117 = Utf8               Code
  #118 = Utf8               LocalVariableTable
  #119 = Utf8               LineNumberTable
  #120 = Utf8               StackMapTable
  #121 = Utf8               RuntimeInvisibleParameterAnnotations
  #122 = Utf8               Signature
  #123 = Utf8               <T:Ljava/lang/Object;U:Ljava/lang/Object;R:Ljava/lang/Object;>(TT;TU;Lkotlin/jvm/functions/Function2<-TT;-TU;+TR;>;)TR;
  #124 = Utf8               SourceFile
  #125 = Utf8               SourceDebugExtension
  #126 = Utf8               RuntimeVisibleAnnotations
{
  public static final void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    Code:
      stack=3, locals=8, args_size=1
         0: aload_0
         1: ldc           #9                  // String args
         3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
         6: iconst_1
         7: istore_1
         8: iconst_2
         9: istore_2
        10: nop
        11: invokestatic  #21                 // Method com/google/common/base/Stopwatch.createStarted:()Lcom/google/common/base/Stopwatch;
        14: astore_3
        15: nop
        16: iload_1
        17: iload_2
        18: istore        4
        20: istore        5
        22: iload         5
        24: iload         4
        26: iadd
        27: istore        5
        29: new           #23                 // class java/lang/StringBuilder
        32: dup
        33: invokespecial #27                 // Method java/lang/StringBuilder."<init>":()V
        36: ldc           #29                 // String call in ns:
        38: invokevirtual #33                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        41: aload_3
        42: getstatic     #39                 // Field java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
        45: invokevirtual #43                 // Method com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
        48: invokevirtual #46                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        51: invokevirtual #50                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        54: astore        4
        56: nop
        57: getstatic     #56                 // Field java/lang/System.out:Ljava/io/PrintStream;
        60: aload         4
        62: invokevirtual #62                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        65: iload         5
        67: goto          111
        70: astore        5
        72: new           #23                 // class java/lang/StringBuilder
        75: dup
        76: invokespecial #27                 // Method java/lang/StringBuilder."<init>":()V
        79: ldc           #29                 // String call in ns:
        81: invokevirtual #33                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        84: aload_3
        85: getstatic     #39                 // Field java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
        88: invokevirtual #43                 // Method com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
        91: invokevirtual #46                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        94: invokevirtual #50                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        97: astore        4
        99: nop
       100: getstatic     #56                 // Field java/lang/System.out:Ljava/io/PrintStream;
       103: aload         4
       105: invokevirtual #62                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       108: aload         5
       110: athrow
       111: pop
       112: return
      Exception table:
         from    to  target type
            15    29    70   any
            70    72    70   any
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           22       5     5     a   I
           22       5     4     b   I
           22       5     6 $i$a$1$timingLog   I
           15      96     3 watch$iv   Lcom/google/common/base/Stopwatch;
           11     100     1  a$iv   I
           11     100     2  b$iv   I
           11     100     7 $i$f$timingLog   I
            0     113     0  args   [Ljava/lang/String;
      LineNumberTable:
        line 14: 6
        line 19: 11
        line 20: 15
        line 21: 16
        line 14: 22
        line 23: 29
        line 23: 72
        line 16: 112
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 70
          locals = [ class "[Ljava/lang/String;", int, int, class com/google/common/base/Stopwatch ]
          stack = [ class java/lang/Throwable ]
        frame_type = 255 /* full_frame */
          offset_delta = 40
          locals = [ class "[Ljava/lang/String;", int, int, class com/google/common/base/Stopwatch, class java/lang/String, int ]
          stack = [ int ]
    RuntimeInvisibleParameterAnnotations:
      0:
        0: #7()

  public static final <T extends java.lang.Object, U extends java.lang.Object, R extends java.lang.Object> R timingLog(T, U, kotlin.jvm.functions.Function2<? super T, ? super U, ? extends R>);
    descriptor: (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    Code:
      stack=3, locals=7, args_size=3
         0: aload_2
         1: ldc           #81                 // String f
         3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
         6: invokestatic  #21                 // Method com/google/common/base/Stopwatch.createStarted:()Lcom/google/common/base/Stopwatch;
         9: astore        4
        11: nop
        12: aload_2
        13: aload_0
        14: aload_1
        15: invokeinterface #87,  3           // InterfaceMethod kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
        20: astore        5
        22: iconst_1
        23: invokestatic  #93                 // Method kotlin/jvm/internal/InlineMarker.finallyStart:(I)V
        26: new           #23                 // class java/lang/StringBuilder
        29: dup
        30: invokespecial #27                 // Method java/lang/StringBuilder."<init>":()V
        33: ldc           #29                 // String call in ns:
        35: invokevirtual #33                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        38: aload         4
        40: getstatic     #39                 // Field java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
        43: invokevirtual #43                 // Method com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
        46: invokevirtual #46                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        49: invokevirtual #50                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        52: astore        6
        54: nop
        55: getstatic     #56                 // Field java/lang/System.out:Ljava/io/PrintStream;
        58: aload         6
        60: invokevirtual #62                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        63: iconst_1
        64: invokestatic  #96                 // Method kotlin/jvm/internal/InlineMarker.finallyEnd:(I)V
        67: aload         5
        69: areturn
        70: astore        5
        72: iconst_1
        73: invokestatic  #93                 // Method kotlin/jvm/internal/InlineMarker.finallyStart:(I)V
        76: new           #23                 // class java/lang/StringBuilder
        79: dup
        80: invokespecial #27                 // Method java/lang/StringBuilder."<init>":()V
        83: ldc           #29                 // String call in ns:
        85: invokevirtual #33                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        88: aload         4
        90: getstatic     #39                 // Field java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
        93: invokevirtual #43                 // Method com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
        96: invokevirtual #46                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        99: invokevirtual #50                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
       102: astore        6
       104: nop
       105: getstatic     #56                 // Field java/lang/System.out:Ljava/io/PrintStream;
       108: aload         6
       110: invokevirtual #62                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       113: iconst_1
       114: invokestatic  #96                 // Method kotlin/jvm/internal/InlineMarker.finallyEnd:(I)V
       117: aload         5
       119: athrow
      Exception table:
         from    to  target type
            11    22    70   any
            70    72    70   any
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           11     109     4 watch   Lcom/google/common/base/Stopwatch;
            0     120     0     a   Ljava/lang/Object;
            0     120     1     b   Ljava/lang/Object;
            0     120     2     f   Lkotlin/jvm/functions/Function2;
            0     120     3 $i$f$timingLog   I
      LineNumberTable:
        line 19: 6
        line 20: 11
        line 21: 12
        line 23: 26
        line 23: 70
        line 23: 76
      StackMapTable: number_of_entries = 1
        frame_type = 255 /* full_frame */
          offset_delta = 70
          locals = [ class java/lang/Object, class java/lang/Object, class kotlin/jvm/functions/Function2, top, class com/google/common/base/Stopwatch ]
          stack = [ class java/lang/Throwable ]
    Signature: #123                         // <T:Ljava/lang/Object;U:Ljava/lang/Object;R:Ljava/lang/Object;>(TT;TU;Lkotlin/jvm/functions/Function2<-TT;-TU;+TR;>;)TR;
    RuntimeInvisibleParameterAnnotations:
      0:
      1:
      2:
        0: #7()
}
SourceFile: "Inlines.kt"
SourceDebugExtension:
  SMAP
  Inlines.kt
  Kotlin
  *S Kotlin
  *F
  + 1 Inlines.kt
  pl/koziolekweb/blog/inlines/InlinesKt
  *L
  1#1,26:1
  *E
RuntimeVisibleAnnotations:
  0: #100(#101=[I#102,I#102,I#102],#103=[I#102,I#104,I#104],#105=I#106,#107=[s#108],#109=[s#5,s#110,s#8,s#110,s#110,s#6,s#78,s#111,s#112,s#113,s#63,s#65,s#80,s#114,s#79,s#115])

To, co nas tu najbardziej interesuje to definicja metody main. Na listingu 3 zaczyna się w linii 134, a na listingu 4 w linii 137. Jak widać w przypadku zastosowania inline metoda main „spuchła” i to znacznie. Po dokładniejszej analizie okaże się, że trafiły do niej wywołania z funkcji timingLog. Zatem proces związany z tym słowem kluczowym polega na „przepisaniu” kodu wywoływanego w miejsce gdzie jest on wywoływany… kojarzycie makra preprocesora z C? W pewien uproszczony sposób można o tym tak myśleć.

Pewnym bonusem jest brak dodatkowego pliku, który pojawia się, gdy nie używamy inline:

Listing 5. bytecode klasy wewnętrznej main

Classfile /home/koziolek/workspace/oldone/blog_old/target/classes/pl/koziolekweb/blog/inlines/InlinesKt$main$1.class
  Last modified 2016-05-23; size 1280 bytes
  MD5 checksum ab966e9707066ff871fe25438fd2debb
  Compiled from "Inlines.kt"
final class pl.koziolekweb.blog.inlines.InlinesKt$main$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function2<java.lang.Integer, java.lang.Integer, java.lang.Integer>
  minor version: 0
  major version: 50
  flags: ACC_FINAL, ACC_SUPER
Constant pool:
   #1 = Utf8               pl/koziolekweb/blog/inlines/InlinesKt$main$1
   #2 = Class              #1             // pl/koziolekweb/blog/inlines/InlinesKt$main$1
   #3 = Utf8               Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function2<Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;>;
   #4 = Utf8               kotlin/jvm/internal/Lambda
   #5 = Class              #4             // kotlin/jvm/internal/Lambda
   #6 = Utf8               kotlin/jvm/functions/Function2
   #7 = Class              #6             // kotlin/jvm/functions/Function2
   #8 = Utf8               invoke
   #9 = Utf8               (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
  #10 = Utf8               java/lang/Number
  #11 = Class              #10            // java/lang/Number
  #12 = Utf8               intValue
  #13 = Utf8               ()I
  #14 = NameAndType        #12:#13        // intValue:()I
  #15 = Methodref          #11.#14        // java/lang/Number.intValue:()I
  #16 = Utf8               (II)I
  #17 = NameAndType        #8:#16         // invoke:(II)I
  #18 = Methodref          #2.#17         // pl/koziolekweb/blog/inlines/InlinesKt$main$1.invoke:(II)I
  #19 = Utf8               java/lang/Integer
  #20 = Class              #19            // java/lang/Integer
  #21 = Utf8               valueOf
  #22 = Utf8               (I)Ljava/lang/Integer;
  #23 = NameAndType        #21:#22        // valueOf:(I)Ljava/lang/Integer;
  #24 = Methodref          #20.#23        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
  #25 = Utf8               this
  #26 = Utf8               Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
  #27 = Utf8               a
  #28 = Utf8               I
  #29 = Utf8               b
  #30 = Utf8               <init>
  #31 = Utf8               ()V
  #32 = Utf8               (I)V
  #33 = NameAndType        #30:#32        // "<init>":(I)V
  #34 = Methodref          #5.#33         // kotlin/jvm/internal/Lambda."<init>":(I)V
  #35 = Utf8               INSTANCE
  #36 = Utf8               <clinit>
  #37 = Utf8               Lkotlin/Metadata;
  #38 = Utf8               mv
  #39 = Integer            1
  #40 = Utf8               bv
  #41 = Integer            0
  #42 = Utf8               k
  #43 = Integer            3
  #44 = Utf8               d1
  #45 = Utf8                \n\n \n\n 02020H\n¢
  #46 = Utf8               d2
  #47 = Utf8               <anonymous>
  #48 = Utf8
  #49 = Utf8               pl/koziolekweb/blog/inlines/InlinesKt
  #50 = Class              #49            // pl/koziolekweb/blog/inlines/InlinesKt
  #51 = Utf8               main
  #52 = Utf8               ([Ljava/lang/String;)V
  #53 = NameAndType        #51:#52        // main:([Ljava/lang/String;)V
  #54 = NameAndType        #30:#31        // "<init>":()V
  #55 = Methodref          #2.#54         // pl/koziolekweb/blog/inlines/InlinesKt$main$1."<init>":()V
  #56 = NameAndType        #35:#26        // INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
  #57 = Fieldref           #2.#56         // pl/koziolekweb/blog/inlines/InlinesKt$main$1.INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
  #58 = Utf8               Inlines.kt
  #59 = Utf8               Code
  #60 = Utf8               LocalVariableTable
  #61 = Utf8               LineNumberTable
  #62 = Utf8               Signature
  #63 = Utf8               SourceFile
  #64 = Utf8               EnclosingMethod
  #65 = Utf8               InnerClasses
  #66 = Utf8               RuntimeVisibleAnnotations
{
  public static final pl.koziolekweb.blog.inlines.InlinesKt$main$1 INSTANCE;
    descriptor: Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

  public java.lang.Object invoke(java.lang.Object, java.lang.Object);
    descriptor: (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
    flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
    Code:
      stack=3, locals=3, args_size=3
         0: aload_0
         1: aload_1
         2: checkcast     #11                 // class java/lang/Number
         5: invokevirtual #15                 // Method java/lang/Number.intValue:()I
         8: aload_2
         9: checkcast     #11                 // class java/lang/Number
        12: invokevirtual #15                 // Method java/lang/Number.intValue:()I
        15: invokevirtual #18                 // Method invoke:(II)I
        18: invokestatic  #24                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        21: areturn

  public final int invoke(int, int);
    descriptor: (II)I
    flags: ACC_PUBLIC, ACC_FINAL
    Code:
      stack=2, locals=3, args_size=3
         0: iload_1
         1: iload_2
         2: iadd
         3: ireturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       4     0  this   Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
            0       4     1     a   I
            0       4     2     b   I
      LineNumberTable:
        line 14: 0

  pl.koziolekweb.blog.inlines.InlinesKt$main$1();
    descriptor: ()V
    flags:
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: iconst_2
         2: invokespecial #34                 // Method kotlin/jvm/internal/Lambda."<init>":(I)V
         5: return

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=2, locals=0, args_size=0
         0: new           #2                  // class pl/koziolekweb/blog/inlines/InlinesKt$main$1
         3: dup
         4: invokespecial #55                 // Method "<init>":()V
         7: putstatic     #57                 // Field INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
        10: return
}
Signature: #3                           // Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function2<Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;>;
SourceFile: "Inlines.kt"
EnclosingMethod: #50.#53                // pl.koziolekweb.blog.inlines.InlinesKt.main
InnerClasses:
     static final #2; //class pl/koziolekweb/blog/inlines/InlinesKt$main$1
RuntimeVisibleAnnotations:
  0: #37(#38=[I#39,I#39,I#39],#40=[I#39,I#41,I#41],#42=I#43,#44=[s#45],#46=[s#47,s#48,s#27,s#29,s#8])

Problemy

Zastosowanie tego mechanizmu spowoduje, że kod „utyje”. I to znacznie. Należy zatem ostrożnie podchodzić do tematu. Co, jeżeli nie chcemy, by któraś z lambd została przepisana? W tym celu należy użyć słowa noinline:

Listing 6. Kod z noinline

fun main(args: Array<String>) {

    timingLog(1, 2, { a, b -> a + b })

}

inline fun <T, U, R>> timingLog(a: T, b: U, noinline f: (T, U) -> R): R {
    val watch = Stopwatch.createStarted()
    try {
        return f(a, b)
    }finally{
        println("call in ns: "  + watch.elapsed(TimeUnit.NANOSECONDS))
    }
}

W efekcie otrzymamy:

Listing 7. Kod z wykorzystaniem noinline

Classfile /home/koziolek/workspace/oldone/blog_old/target/classes/pl/koziolekweb/blog/inlines/InlinesKt.class
  Last modified 2016-05-23; size 3106 bytes
  MD5 checksum 01984b401a79bd5e6653d4100a183017
  Compiled from "Inlines.kt"
public final class pl.koziolekweb.blog.inlines.InlinesKt
  minor version: 0
  major version: 50
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
Constant pool:
    #1 = Utf8               pl/koziolekweb/blog/inlines/InlinesKt
    #2 = Class              #1            // pl/koziolekweb/blog/inlines/InlinesKt
    #3 = Utf8               java/lang/Object
    #4 = Class              #3            // java/lang/Object
    #5 = Utf8               main
    #6 = Utf8               ([Ljava/lang/String;)V
    #7 = Utf8               Lorg/jetbrains/annotations/NotNull;
    #8 = Utf8               args
    #9 = String             #8            // args
   #10 = Utf8               kotlin/jvm/internal/Intrinsics
   #11 = Class              #10           // kotlin/jvm/internal/Intrinsics
   #12 = Utf8               checkParameterIsNotNull
   #13 = Utf8               (Ljava/lang/Object;Ljava/lang/String;)V
   #14 = NameAndType        #12:#13       // checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
   #15 = Methodref          #11.#14       // kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
   #16 = Utf8               java/lang/Integer
   #17 = Class              #16           // java/lang/Integer
   #18 = Utf8               valueOf
   #19 = Utf8               (I)Ljava/lang/Integer;
   #20 = NameAndType        #18:#19       // valueOf:(I)Ljava/lang/Integer;
   #21 = Methodref          #17.#20       // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #22 = Utf8               pl/koziolekweb/blog/inlines/InlinesKt$main$1
   #23 = Class              #22           // pl/koziolekweb/blog/inlines/InlinesKt$main$1
   #24 = Utf8               INSTANCE
   #25 = Utf8               Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
   #26 = NameAndType        #24:#25       // INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
   #27 = Fieldref           #23.#26       // pl/koziolekweb/blog/inlines/InlinesKt$main$1.INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
   #28 = Utf8               kotlin/jvm/functions/Function2
   #29 = Class              #28           // kotlin/jvm/functions/Function2
   #30 = Utf8               com/google/common/base/Stopwatch
   #31 = Class              #30           // com/google/common/base/Stopwatch
   #32 = Utf8               createStarted
   #33 = Utf8               ()Lcom/google/common/base/Stopwatch;
   #34 = NameAndType        #32:#33       // createStarted:()Lcom/google/common/base/Stopwatch;
   #35 = Methodref          #31.#34       // com/google/common/base/Stopwatch.createStarted:()Lcom/google/common/base/Stopwatch;
   #36 = Utf8               invoke
   #37 = Utf8               (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   #38 = NameAndType        #36:#37       // invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   #39 = InterfaceMethodref #29.#38       // kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   #40 = Utf8               java/lang/StringBuilder
   #41 = Class              #40           // java/lang/StringBuilder
   #42 = Utf8               <init>
   #43 = Utf8               ()V
   #44 = NameAndType        #42:#43       // "<init>":()V
   #45 = Methodref          #41.#44       // java/lang/StringBuilder."<init>":()V
   #46 = Utf8               call in ns:
   #47 = String             #46           // call in ns:
   #48 = Utf8               append
   #49 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
   #50 = NameAndType        #48:#49       // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #51 = Methodref          #41.#50       // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #52 = Utf8               java/util/concurrent/TimeUnit
   #53 = Class              #52           // java/util/concurrent/TimeUnit
   #54 = Utf8               NANOSECONDS
   #55 = Utf8               Ljava/util/concurrent/TimeUnit;
   #56 = NameAndType        #54:#55       // NANOSECONDS:Ljava/util/concurrent/TimeUnit;
   #57 = Fieldref           #53.#56       // java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
   #58 = Utf8               elapsed
   #59 = Utf8               (Ljava/util/concurrent/TimeUnit;)J
   #60 = NameAndType        #58:#59       // elapsed:(Ljava/util/concurrent/TimeUnit;)J
   #61 = Methodref          #31.#60       // com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
   #62 = Utf8               (J)Ljava/lang/StringBuilder;
   #63 = NameAndType        #48:#62       // append:(J)Ljava/lang/StringBuilder;
   #64 = Methodref          #41.#63       // java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
   #65 = Utf8               toString
   #66 = Utf8               ()Ljava/lang/String;
   #67 = NameAndType        #65:#66       // toString:()Ljava/lang/String;
   #68 = Methodref          #41.#67       // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #69 = Utf8               java/lang/System
   #70 = Class              #69           // java/lang/System
   #71 = Utf8               out
   #72 = Utf8               Ljava/io/PrintStream;
   #73 = NameAndType        #71:#72       // out:Ljava/io/PrintStream;
   #74 = Fieldref           #70.#73       // java/lang/System.out:Ljava/io/PrintStream;
   #75 = Utf8               java/io/PrintStream
   #76 = Class              #75           // java/io/PrintStream
   #77 = Utf8               println
   #78 = Utf8               (Ljava/lang/Object;)V
   #79 = NameAndType        #77:#78       // println:(Ljava/lang/Object;)V
   #80 = Methodref          #76.#79       // java/io/PrintStream.println:(Ljava/lang/Object;)V
   #81 = Utf8               watch$iv
   #82 = Utf8               Lcom/google/common/base/Stopwatch;
   #83 = Utf8               a$iv
   #84 = Utf8               Ljava/lang/Object;
   #85 = Utf8               b$iv
   #86 = Utf8               f$iv
   #87 = Utf8               Lkotlin/jvm/functions/Function2;
   #88 = Utf8               $i$f$timingLog
   #89 = Utf8               I
   #90 = Utf8               [Ljava/lang/String;
   #91 = Class              #90           // "[Ljava/lang/String;"
   #92 = Utf8               java/lang/Throwable
   #93 = Class              #92           // java/lang/Throwable
   #94 = Utf8               java/lang/String
   #95 = Class              #94           // java/lang/String
   #96 = Utf8               timingLog
   #97 = Utf8               (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
   #98 = Utf8               f
   #99 = String             #98           // f
  #100 = Utf8               kotlin/jvm/internal/InlineMarker
  #101 = Class              #100          // kotlin/jvm/internal/InlineMarker
  #102 = Utf8               finallyStart
  #103 = Utf8               (I)V
  #104 = NameAndType        #102:#103     // finallyStart:(I)V
  #105 = Methodref          #101.#104     // kotlin/jvm/internal/InlineMarker.finallyStart:(I)V
  #106 = Utf8               finallyEnd
  #107 = NameAndType        #106:#103     // finallyEnd:(I)V
  #108 = Methodref          #101.#107     // kotlin/jvm/internal/InlineMarker.finallyEnd:(I)V
  #109 = Utf8               watch
  #110 = Utf8               a
  #111 = Utf8               b
  #112 = Utf8               Lkotlin/Metadata;
  #113 = Utf8               mv
  #114 = Integer            1
  #115 = Utf8               bv
  #116 = Integer            0
  #117 = Utf8               k
  #118 = Integer            2
  #119 = Utf8               d1
  #120 = Utf8                \n \n\n \n\n\n\n\n 0200¢LH\" \"\t\"2\nH2H\t2HH\tH0\rH†¢¨
  #121 = Utf8               d2
  #122 = Utf8
  #123 = Utf8               R
  #124 = Utf8               T
  #125 = Utf8               U
  #126 = Utf8               Lkotlin/Function2;
  #127 = Utf8               blog
  #128 = Utf8               Inlines.kt
  #129 = Utf8               Code
  #130 = Utf8               LocalVariableTable
  #131 = Utf8               LineNumberTable
  #132 = Utf8               StackMapTable
  #133 = Utf8               RuntimeInvisibleParameterAnnotations
  #134 = Utf8               Signature
  #135 = Utf8               <T:Ljava/lang/Object;U:Ljava/lang/Object;R:Ljava/lang/Object;>(TT;TU;Lkotlin/jvm/functions/Function2<-TT;-TU;+TR;>;)TR;
  #136 = Utf8               SourceFile
  #137 = Utf8               SourceDebugExtension
  #138 = Utf8               InnerClasses
  #139 = Utf8               RuntimeVisibleAnnotations
{
  public static final void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    Code:
      stack=3, locals=8, args_size=1
         0: aload_0
         1: ldc           #9                  // String args
         3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
         6: iconst_1
         7: invokestatic  #21                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        10: astore_1
        11: iconst_2
        12: invokestatic  #21                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        15: astore_2
        16: getstatic     #27                 // Field pl/koziolekweb/blog/inlines/InlinesKt$main$1.INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
        19: checkcast     #29                 // class kotlin/jvm/functions/Function2
        22: astore_3
        23: nop
        24: invokestatic  #35                 // Method com/google/common/base/Stopwatch.createStarted:()Lcom/google/common/base/Stopwatch;
        27: astore        4
        29: nop
        30: aload_3
        31: aload_1
        32: aload_2
        33: invokeinterface #39,  3           // InterfaceMethod kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
        38: astore        5
        40: new           #41                 // class java/lang/StringBuilder
        43: dup
        44: invokespecial #45                 // Method java/lang/StringBuilder."<init>":()V
        47: ldc           #47                 // String call in ns:
        49: invokevirtual #51                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        52: aload         4
        54: getstatic     #57                 // Field java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
        57: invokevirtual #61                 // Method com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
        60: invokevirtual #64                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        63: invokevirtual #68                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        66: astore        6
        68: nop
        69: getstatic     #74                 // Field java/lang/System.out:Ljava/io/PrintStream;
        72: aload         6
        74: invokevirtual #80                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        77: aload         5
        79: goto          124
        82: astore        5
        84: new           #41                 // class java/lang/StringBuilder
        87: dup
        88: invokespecial #45                 // Method java/lang/StringBuilder."<init>":()V
        91: ldc           #47                 // String call in ns:
        93: invokevirtual #51                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        96: aload         4
        98: getstatic     #57                 // Field java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
       101: invokevirtual #61                 // Method com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
       104: invokevirtual #64                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
       107: invokevirtual #68                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
       110: astore        6
       112: nop
       113: getstatic     #74                 // Field java/lang/System.out:Ljava/io/PrintStream;
       116: aload         6
       118: invokevirtual #80                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       121: aload         5
       123: athrow
       124: pop
       125: return
      Exception table:
         from    to  target type
            29    40    82   any
            82    84    82   any
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           29      95     4 watch$iv   Lcom/google/common/base/Stopwatch;
           24     100     1  a$iv   Ljava/lang/Object;
           24     100     2  b$iv   Ljava/lang/Object;
           24     100     3  f$iv   Lkotlin/jvm/functions/Function2;
           24     100     7 $i$f$timingLog   I
            0     126     0  args   [Ljava/lang/String;
      LineNumberTable:
        line 14: 6
        line 19: 24
        line 20: 29
        line 21: 30
        line 23: 40
        line 23: 84
        line 16: 125
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 82
          locals = [ class "[Ljava/lang/String;", class java/lang/Integer, class java/lang/Integer, class kotlin/jvm/functions/Function2, class com/google/common/base/Stopwatch ]
          stack = [ class java/lang/Throwable ]
        frame_type = 255 /* full_frame */
          offset_delta = 41
          locals = [ class "[Ljava/lang/String;", class java/lang/Integer, class java/lang/Integer, class kotlin/jvm/functions/Function2, class com/google/common/base/Stopwatch, class java/lang/Object, class java/lang/String ]
          stack = [ class java/lang/Object ]
    RuntimeInvisibleParameterAnnotations:
      0:
        0: #7()

  public static final <T extends java.lang.Object, U extends java.lang.Object, R extends java.lang.Object> R timingLog(T, U, kotlin.jvm.functions.Function2<? super T, ? super U, ? extends R>);
    descriptor: (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    Code:
      stack=3, locals=7, args_size=3
         0: aload_2
         1: ldc           #99                 // String f
         3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
         6: invokestatic  #35                 // Method com/google/common/base/Stopwatch.createStarted:()Lcom/google/common/base/Stopwatch;
         9: astore        4
        11: nop
        12: aload_2
        13: aload_0
        14: aload_1
        15: invokeinterface #39,  3           // InterfaceMethod kotlin/jvm/functions/Function2.invoke:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
        20: astore        5
        22: iconst_1
        23: invokestatic  #105                // Method kotlin/jvm/internal/InlineMarker.finallyStart:(I)V
        26: new           #41                 // class java/lang/StringBuilder
        29: dup
        30: invokespecial #45                 // Method java/lang/StringBuilder."<init>":()V
        33: ldc           #47                 // String call in ns:
        35: invokevirtual #51                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        38: aload         4
        40: getstatic     #57                 // Field java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
        43: invokevirtual #61                 // Method com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
        46: invokevirtual #64                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        49: invokevirtual #68                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        52: astore        6
        54: nop
        55: getstatic     #74                 // Field java/lang/System.out:Ljava/io/PrintStream;
        58: aload         6
        60: invokevirtual #80                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
        63: iconst_1
        64: invokestatic  #108                // Method kotlin/jvm/internal/InlineMarker.finallyEnd:(I)V
        67: aload         5
        69: areturn
        70: astore        5
        72: iconst_1
        73: invokestatic  #105                // Method kotlin/jvm/internal/InlineMarker.finallyStart:(I)V
        76: new           #41                 // class java/lang/StringBuilder
        79: dup
        80: invokespecial #45                 // Method java/lang/StringBuilder."<init>":()V
        83: ldc           #47                 // String call in ns:
        85: invokevirtual #51                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        88: aload         4
        90: getstatic     #57                 // Field java/util/concurrent/TimeUnit.NANOSECONDS:Ljava/util/concurrent/TimeUnit;
        93: invokevirtual #61                 // Method com/google/common/base/Stopwatch.elapsed:(Ljava/util/concurrent/TimeUnit;)J
        96: invokevirtual #64                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        99: invokevirtual #68                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
       102: astore        6
       104: nop
       105: getstatic     #74                 // Field java/lang/System.out:Ljava/io/PrintStream;
       108: aload         6
       110: invokevirtual #80                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       113: iconst_1
       114: invokestatic  #108                // Method kotlin/jvm/internal/InlineMarker.finallyEnd:(I)V
       117: aload         5
       119: athrow
      Exception table:
         from    to  target type
            11    22    70   any
            70    72    70   any
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
           11     109     4 watch   Lcom/google/common/base/Stopwatch;
            0     120     0     a   Ljava/lang/Object;
            0     120     1     b   Ljava/lang/Object;
            0     120     2     f   Lkotlin/jvm/functions/Function2;
            0     120     3 $i$f$timingLog   I
      LineNumberTable:
        line 19: 6
        line 20: 11
        line 21: 12
        line 23: 26
        line 23: 70
        line 23: 76
      StackMapTable: number_of_entries = 1
        frame_type = 255 /* full_frame */
          offset_delta = 70
          locals = [ class java/lang/Object, class java/lang/Object, class kotlin/jvm/functions/Function2, top, class com/google/common/base/Stopwatch ]
          stack = [ class java/lang/Throwable ]
    Signature: #135                         // <T:Ljava/lang/Object;U:Ljava/lang/Object;R:Ljava/lang/Object;>(TT;TU;Lkotlin/jvm/functions/Function2<-TT;-TU;+TR;>;)TR;
    RuntimeInvisibleParameterAnnotations:
      0:
      1:
      2:
        0: #7()
}
SourceFile: "Inlines.kt"
SourceDebugExtension:
  SMAP
  Inlines.kt
  Kotlin
  *S Kotlin
  *F
  + 1 Inlines.kt
  pl/koziolekweb/blog/inlines/InlinesKt
  *L
  1#1,28:1
  *E
InnerClasses:
     static final #23; //class pl/koziolekweb/blog/inlines/InlinesKt$main$1
RuntimeVisibleAnnotations:
  0: #112(#113=[I#114,I#114,I#114],#115=[I#114,I#116,I#116],#117=I#118,#119=[s#120],#121=[s#5,s#122,s#8,s#122,s#122,s#6,s#96,s#123,s#124,s#125,s#110,s#111,s#98,s#126,s#97,s#127])

W linii 174 mamy wywołanie lambdy oddelegowane do InlinesKt$main$1, utworzonego w linii 164. I jeszcze kod InlinesKt$main$1:

Listing 8. Kod dodatkowo wygenerowanej klasy wewnętrznej

Classfile /home/koziolek/workspace/oldone/blog_old/target/classes/pl/koziolekweb/blog/inlines/InlinesKt$main$1.class
  Last modified 2016-05-23; size 1280 bytes
  MD5 checksum ab966e9707066ff871fe25438fd2debb
  Compiled from "Inlines.kt"
final class pl.koziolekweb.blog.inlines.InlinesKt$main$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function2<java.lang.Integer, java.lang.Integer, java.lang.Integer>
  minor version: 0
  major version: 50
  flags: ACC_FINAL, ACC_SUPER
Constant pool:
   #1 = Utf8               pl/koziolekweb/blog/inlines/InlinesKt$main$1
   #2 = Class              #1             // pl/koziolekweb/blog/inlines/InlinesKt$main$1
   #3 = Utf8               Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function2<Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;>;
   #4 = Utf8               kotlin/jvm/internal/Lambda
   #5 = Class              #4             // kotlin/jvm/internal/Lambda
   #6 = Utf8               kotlin/jvm/functions/Function2
   #7 = Class              #6             // kotlin/jvm/functions/Function2
   #8 = Utf8               invoke
   #9 = Utf8               (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
  #10 = Utf8               java/lang/Number
  #11 = Class              #10            // java/lang/Number
  #12 = Utf8               intValue
  #13 = Utf8               ()I
  #14 = NameAndType        #12:#13        // intValue:()I
  #15 = Methodref          #11.#14        // java/lang/Number.intValue:()I
  #16 = Utf8               (II)I
  #17 = NameAndType        #8:#16         // invoke:(II)I
  #18 = Methodref          #2.#17         // pl/koziolekweb/blog/inlines/InlinesKt$main$1.invoke:(II)I
  #19 = Utf8               java/lang/Integer
  #20 = Class              #19            // java/lang/Integer
  #21 = Utf8               valueOf
  #22 = Utf8               (I)Ljava/lang/Integer;
  #23 = NameAndType        #21:#22        // valueOf:(I)Ljava/lang/Integer;
  #24 = Methodref          #20.#23        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
  #25 = Utf8               this
  #26 = Utf8               Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
  #27 = Utf8               a
  #28 = Utf8               I
  #29 = Utf8               b
  #30 = Utf8               <init>
  #31 = Utf8               ()V
  #32 = Utf8               (I)V
  #33 = NameAndType        #30:#32        // "<init>":(I)V
  #34 = Methodref          #5.#33         // kotlin/jvm/internal/Lambda."<init>":(I)V
  #35 = Utf8               INSTANCE
  #36 = Utf8               <clinit>
  #37 = Utf8               Lkotlin/Metadata;
  #38 = Utf8               mv
  #39 = Integer            1
  #40 = Utf8               bv
  #41 = Integer            0
  #42 = Utf8               k
  #43 = Integer            3
  #44 = Utf8               d1
  #45 = Utf8                \n\n \n\n 02020H\n¢
  #46 = Utf8               d2
  #47 = Utf8               <anonymous>
  #48 = Utf8
  #49 = Utf8               pl/koziolekweb/blog/inlines/InlinesKt
  #50 = Class              #49            // pl/koziolekweb/blog/inlines/InlinesKt
  #51 = Utf8               main
  #52 = Utf8               ([Ljava/lang/String;)V
  #53 = NameAndType        #51:#52        // main:([Ljava/lang/String;)V
  #54 = NameAndType        #30:#31        // "<init>":()V
  #55 = Methodref          #2.#54         // pl/koziolekweb/blog/inlines/InlinesKt$main$1."<init>":()V
  #56 = NameAndType        #35:#26        // INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
  #57 = Fieldref           #2.#56         // pl/koziolekweb/blog/inlines/InlinesKt$main$1.INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
  #58 = Utf8               Inlines.kt
  #59 = Utf8               Code
  #60 = Utf8               LocalVariableTable
  #61 = Utf8               LineNumberTable
  #62 = Utf8               Signature
  #63 = Utf8               SourceFile
  #64 = Utf8               EnclosingMethod
  #65 = Utf8               InnerClasses
  #66 = Utf8               RuntimeVisibleAnnotations
{
  public static final pl.koziolekweb.blog.inlines.InlinesKt$main$1 INSTANCE;
    descriptor: Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

  public java.lang.Object invoke(java.lang.Object, java.lang.Object);
    descriptor: (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
    flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
    Code:
      stack=3, locals=3, args_size=3
         0: aload_0
         1: aload_1
         2: checkcast     #11                 // class java/lang/Number
         5: invokevirtual #15                 // Method java/lang/Number.intValue:()I
         8: aload_2
         9: checkcast     #11                 // class java/lang/Number
        12: invokevirtual #15                 // Method java/lang/Number.intValue:()I
        15: invokevirtual #18                 // Method invoke:(II)I
        18: invokestatic  #24                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        21: areturn

  public final int invoke(int, int);
    descriptor: (II)I
    flags: ACC_PUBLIC, ACC_FINAL
    Code:
      stack=2, locals=3, args_size=3
         0: iload_1
         1: iload_2
         2: iadd
         3: ireturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       4     0  this   Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
            0       4     1     a   I
            0       4     2     b   I
      LineNumberTable:
        line 14: 0

  pl.koziolekweb.blog.inlines.InlinesKt$main$1();
    descriptor: ()V
    flags:
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: iconst_2
         2: invokespecial #34                 // Method kotlin/jvm/internal/Lambda."<init>":(I)V
         5: return

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=2, locals=0, args_size=0
         0: new           #2                  // class pl/koziolekweb/blog/inlines/InlinesKt$main$1
         3: dup
         4: invokespecial #55                 // Method "<init>":()V
         7: putstatic     #57                 // Field INSTANCE:Lpl/koziolekweb/blog/inlines/InlinesKt$main$1;
        10: return
}
Signature: #3                           // Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function2<Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Integer;>;
SourceFile: "Inlines.kt"
EnclosingMethod: #50.#53                // pl.koziolekweb.blog.inlines.InlinesKt.main
InnerClasses:
     static final #2; //class pl/koziolekweb/blog/inlines/InlinesKt$main$1
RuntimeVisibleAnnotations:
  0: #37(#38=[I#39,I#39,I#39],#40=[I#39,I#41,I#41],#42=I#43,#44=[s#45],#46=[s#47,s#48,s#27,s#29,s#8])

Podsumowanie

Jak zwykle, coś za coś. Z jednej strony mechanizm powiązany z inliningiem pozwala na stworzenie szybszego kodu, pozbawionego narzutu związanego z wywoływaniem warstw pośredniczących. Z drugiej strony taki kod będzie miał większy rozmiar. Nie jest to bez znaczenia w przypadku aplikacji mobilnych. Dla ciekawskich zadanie ustawcie debugger na wywołaniu funkcji f w timingLog i zobaczcie, jak wygląda stos wywołań w obu przypadkach.

Napisz odpowiedź

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax