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

Dive into JVM JIT Compiler

Dive into JVM JIT Compiler

Explained what is happening in the JITCompiler of the JVM called HotSpotVM by looking at a compiled assembly.

Ikuo Suyama

August 10, 2022
Tweet

More Decks by Ikuo Suyama

Other Decks in Programming

Transcript

  1. ΠϯλϓϦλͱίϯύΠϥ 'JCKBWB package jit; public class Fib { public static

    void main(String[] args) { int i = Integer.valueOf(args[0]); System.out.println(fib(i)); } private static int fib(int i) { if (i <= 0) { return 0; } else if (i == 1) { return 1; } else { return (fib(i - 1) + fib(i - 2)); } } } ❯ javac Fib.java ❯ javap -v -p -s -constants Fib.class > Fib.jvm private static int fib(int); descriptor: (I)I flags: (0x000a) ACC_PRIVATE, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: iload_0 1: ifgt 6 4: iconst_0 5: ireturn 6: iload_0 7: iconst_1 8: if_icmpne 13 11: iconst_1 12: ireturn 13: iload_0 14: iconst_1 15: isub 16: invokestatic #5 // Method fib:(I)I 19: iload_0 20: iconst_2 21: isub 22: invokestatic #5 // Method fib:(I)I 25: iadd 26: ireturn 'JCKWN fi CϝιουͷΈൈਮ ΈΜͳେ޷͖ϑΟϘφον਺Λ ࠶ؼͰܭࢉ͢ΔΫϥε +7.Ϛγϯޠ͸ΠϯλϓϦλʢஞ࣮࣍ߦʣݴޠ
  2. ΠϯλϓϦλͱίϯύΠϥ 'JCKBWB package jit; public class Fib { public static

    void main(String[] args) { int i = Integer.valueOf(args[0]); System.out.println(fib(i)); } private static int fib(int i) { if (i <= 0) { return 0; } else if (i == 1) { return 1; } else { return (fib(i - 1) + fib(i - 2)); } } } ❯ javac Fib.java ❯ javap -v -p -s -constants Fib.class > Fib.jvm private static int fib(int); descriptor: (I)I flags: (0x000a) ACC_PRIVATE, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: iload_0 1: ifgt 6 4: iconst_0 5: ireturn 6: iload_0 7: iconst_1 8: if_icmpne 13 11: iconst_1 12: ireturn 13: iload_0 14: iconst_1 15: isub 16: invokestatic #5 // Method fib:(I)I 19: iload_0 20: iconst_2 21: isub 22: invokestatic #5 // Method fib:(I)I 25: iadd 26: ireturn 'JCKWN fi CϝιουͷΈൈਮ ͜Μͳײ͡Ͱͨ͠Ͷʁ +7.Ϛγϯޠ͸ΠϯλϓϦλʢஞ࣮࣍ߦʣݴޠ
  3. ΠϯλϓϦλͱίϯύΠϥ private static int fib(int); descriptor: (I)I flags: (0x000a) ACC_PRIVATE,

    ACC_STATIC Code: stack=3, locals=1, args_size=1 0: iload_0 1: ifgt 6 4: iconst_0 5: ireturn 6: iload_0 7: iconst_1 8: if_icmpne 13 11: iconst_1 12: ireturn 13: iload_0 14: iconst_1 15: isub 16: invokestatic #5 // Method fib:(I)I 19: iload_0 20: iconst_2 21: isub 22: invokestatic #5 // Method fib:(I)I 25: iadd 26: ireturn +7.Ϛγϯޠ͸ΠϯλϓϦλʢஞ࣮࣍ߦʣݴޠ
  4. ΠϯλϓϦλͱίϯύΠϥ private static int fib(int); descriptor: (I)I flags: (0x000a) ACC_PRIVATE,

    ACC_STATIC Code: stack=3, locals=1, args_size=1 0: iload_0 1: ifgt 6 4: iconst_0 5: ireturn 6: iload_0 7: iconst_1 8: if_icmpne 13 11: iconst_1 12: ireturn 13: iload_0 14: iconst_1 15: isub 16: invokestatic #5 // Method fib:(I)I 19: iload_0 20: iconst_2 21: isub 22: invokestatic #5 // Method fib:(I)I 25: iadd 26: ireturn +7.Ϛγϯޠ͸ΠϯλϓϦλʢஞ࣮࣍ߦʣݴޠ iload_0 = 26 (0x1a) iconst_1 = 4 (0x4) isub = 100 (0x64) invokestatic = 184 (0xb8) indexbyte1 indexbyte2 KBWBD͸͜ͷΑ͏ʹɺ ॻ͍ͯ͋Δ͜ͱΛجຊͦͷ··+7.ΠϯετϥΫγϣϯʹ༁͠ɺ +7.͸͜ΕΛ্͔Βஞ࣮࣍ߦ͢Δ
  5. ΠϯλϓϦλͱίϯύΠϥ ύϑΥʔϚϯε͸Ͳ͏͔ʁ 9JOUʜJOUFSQSJUFSϞʔυͷΈͰ࣮ߦ .BDCPPL1SPJODI()DPSFJ ͰTdNJOɻ஗͍ʁ ❯ time java -Xint jit.Fib

    48 512559680 ________________________________________________________ Executed in 847.43 secs fish external usr time 844.04 secs 119.00 micros 844.04 secs sys time 1.79 secs 898.00 micros 1.79 secs
  6. ΠϯλϓϦλͱίϯύΠϥ ݟͤͯ΋Β͏͔ɺ+*5ίϯύΠϥ͕ੜ੒͢ΔΞηϯϒϦͱ΍ΒΛ ❯ sudo wget https://raw.githubusercontent.com/a10y/hsdis-macos/master/hsdis-amd64.dylib \ $JAVA_HOME/lib/server/ ❯ java

    \ -XX:+UnlockDiagnosticVMOptions \ -XX:-PrintAssembly \ -XX:+PrintInterpreter \ jit.Fib 10 > Fib.fib.int.print ˞όΠφϦͷग़ྗʹ͸ITEJT͕ඞཁɻ ITEJTBNEEZMJC GPS*OUFM.BD Λ+"7"@)0.&MJCʹೖΕ͓ͯ͘
  7. ΠϯλϓϦλͱίϯύΠϥ ݟͤͯ΋Β͏͔ɺ+*5ίϯύΠϥ͕ੜ੒͢ΔΞηϯϒϦͱ΍ΒΛ ---------------------------------------------------------------------- iload_0 26 iload_0 [0x0000000124986bc0, 0x0000000124986c20] 96 bytes

    0x0000000124986bc0: push %rax 0x0000000124986bc1: jmpq 0x0000000124986bff 0x0000000124986bc6: sub $0x8,%rsp 0x0000000124986bca: vmovss %xmm0,(%rsp) 0x0000000124986bcf: jmpq 0x0000000124986bff 0x0000000124986bd4: sub $0x10,%rsp 0x0000000124986bd8: vmovsd %xmm0,(%rsp) 0x0000000124986bdd: jmpq 0x0000000124986bff 0x0000000124986be2: sub $0x10,%rsp 0x0000000124986be6: mov %rax,(%rsp) 0x0000000124986bea: movabs $0x0,%r10 0x0000000124986bf4: mov %r10,0x8(%rsp) 0x0000000124986bf9: jmpq 0x0000000124986bff 0x0000000124986bfe: push %rax 0x0000000124986bff: mov (%r14),%eax 0x0000000124986c02: movzbl 0x1(%r13),%ebx 0x0000000124986c07: inc %r13 0x0000000124986c0a: movabs $0x1151d5220,%r10 0x0000000124986c14: jmpq *(%r10,%rbx,8) 0x0000000124986c18: add %al,(%rax) 0x0000000124986c1a: add %al,(%rax) 0x0000000124986c1c: add %al,(%rax) 0x0000000124986c1e: add %al,(%rax) private static int fib(int); descriptor: (I)I flags: (0x000a) ACC_PRIVATE, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: iload_0 1: ifgt 6 4: iconst_0 5: ireturn 6: iload_0 7: iconst_1 8: if_icmpne 13 11: iconst_1 12: ireturn 13: iload_0 14: iconst_1 15: isub 16: invokestatic #5 // Method fib:(I)I 19: iload_0 20: iconst_2 21: isub 22: invokestatic #5 // Method fib:(I)I 25: iadd 26: ireturn ͔ͨ͠ʹɺ֤ΠϯετϥΫγϣϯͷ όΠφϦεχϖοτ͕ੜ੒͞Ε͍ͯΔʂ
  8. +7.+*5$PNQJMFS +*5$PNQJMFSΛ0Oʹͯ͠ɺ࠶౓'JCΛ࣮ߦͯ͠ΈΔ ❯ time java jit.Fib 48 : ________________________________________________________ Executed

    in 19.04 secs fish external usr time 18.93 secs 111.00 micros 18.93 secs sys time 0.11 secs 811.00 micros 0.11 secs ❯ time java -Xint jit.Fib 48 512559680 ________________________________________________________ Executed in 847.43 secs fish external usr time 844.04 secs 119.00 micros 844.04 secs sys time 1.79 secs 898.00 micros 1.79 secs TT໿ഒͷߴ଎Խ
  9. +7.+*5$PNQJMFS ❯ time java -XX:+PrintCompilation jit.Fib 48 38 1 3

    java.lang.StringLatin1::hashCode (42 bytes) 39 2 3 java.util.concurrent.ConcurrentHashMap::tabAt (22 bytes) 39 4 n 0 jdk.internal.misc.Unsafe::getObjectVolatile (native) : 70 89 3 jit.Fib::fib (27 bytes) 71 90 4 jit.Fib::fib (27 bytes) 72 89 3 jit.Fib::fib (27 bytes) made not entrant ίϯύΠϧͷ༷ࢠΛ೷͍ͯΈΔ99 1SJOU$PNQJMBUJPO Format: $1: $2 $3 $4 $5 ($6 bytes) $7 —— $1: JavaϝιουͷίϯύΠϧཁٻൃੜ࣌ؒ(ϩάग़ྗ࣌ͷ࣌ؒ) $2: ௨͠൪߸ $3: ۭന·ͨ͸ϝιουͷίϯύΠϧछผ $4:ۭന·ͨ͸ϝιουͷίϯύΠϧϨϕϧ $5: Javaϝιου໊ $6: JavaϝιουͷόΠτ਺·ͨ͸(native) $7: ۭന·ͨ͸(static)·ͨ͸ made not entrant fi Cϝιου͕ෳ਺ճίϯύΠϧ͞Ε͍ͯΔ
  10. )PU4QPU7. DMJFOUDPNQJMFS $ TFSWFSDPNQJMFS $  +7. ͸΍ͨΒΊͬͨΒͦ͜Β͡Ύ͏ΛίϯύΠϧ͢ΔΘ͚Ͱ͸ͳ͍  ਖ਼֬ʹ͸Ͱ͖ͳ͍ʜ+*5ɺͭ·ΓΦϯϥΠϯͰίϯύΠϧΛ͍ͯ͠Δʂ

     ద੾ͳՕॴΛɺద੾ͳλΠϛϯάΛݟܭΒͬͯίϯύΠϧ͍ͯ͠Δ  ׂͷ࣌ؒ͸ɺׂͷίʔυ͔Β͘Δ  ద੾ͳՕॴʁ  Α࣮͘ߦ͞ΕΔ৔ॴŠ)PU4QPU  ద੾ͳλΠϛϯάʁ  ͭͷίϯύΠϥ ಛఆͷ࣮૷ͷɻ)PU4QPUͰͳ͍+7.΋ଘࡏ͢Δ
  11. )PU4QPU7. DMJFOUDPNQJMFS $ TFSWFSDPNQJMFS $ $MJFOU$PNQJMFS $-FWFM 4FSWFS$PNQJMFS $-FWFM ϝιουΛ͢͹΍͘ίϯύΠϧ͠·͕͢ɺαʔόʔɾίϯύ

    Πϥ΄Ͳ͸࠷దԽ͞Εͳ͍ϚγϯɾίʔυΛੜ੒͠·͢ɻ ͜ͷίϯύΠϥΛ࢖༻͢Δͱɺਝ଎ʹىಈ͠·͢ɻ ·ͨɺ͜ͷίϯύΠϥͰ͸ɺগͳ͍ϝϞϦʔɾϑοτϓϦϯ τ͕ఆৗύϑΥʔϚϯεΑΓॏཁͰ͢ɻ ͜ͷίϯύΠϥ͸ɺಉ͡ϝιουͷίϯύΠϧʹΑΓଟ͘ͷ ͕͔͔࣌ؒΓ·͢ ͓ΑͼΑΓଟ͘ͷϝϞϦʔΛফඅ͠·͢ ɻ ͨͩ͠ɺΫϥΠΞϯτɾίϯύΠϥͰੜ੒ͨ͠ίʔυΑΓ࠷ దԽ͞ΕͨϚγϯɾίʔυΛੜ੒͠·͢ɻ ΞϓϦέʔγϣϯ͕ఆৗʹୡͨ͠ޙ͸ɺ࣮ߦ࣌ύϑΥʔϚϯ ε͕޲্͠·͢ɻ ŠίϯύΠϧ࠷దԽ0SBDMF w ίϯύΠϧ͕ૣ͍ɺ͍ܰʢ$16.&.ʣ w ੑೳ͸ͦͦ͜͜ w ࢖͍ॴ w ϥΠϑλΠϜ͕୹͍ʢ$MJFOU"QQMJDBUJPOʣ w "QQMJDBUJPO#PPUTUSBQ w ίϯύΠϧ͕௕͍ɺॏ͍ w ੑೳ͸όϦόϦ w ࢖͍ॴ w ϥΠϑλΠϜ͕௕͍ʢ4FSWFS"QQMJDBUJPOʣ w "GUFS#PPUTUSBQ
  12. +7.+*5$PNQJMFS τϨʔυΦϑͱ֊૚ίϯύΠϧ ❯ java -XX:+PrintCompilation jit.Fib 48 38 1 3

    java.lang.StringLatin1::hashCode (42 bytes) 39 2 3 java.util.concurrent.ConcurrentHashMap::tabAt (22 bytes) 39 4 n 0 jdk.internal.misc.Unsafe::getObjectVolatile (native) 39 3 3 jdk.internal.misc.Unsafe::getObjectAcquire (7 bytes) 40 5 3 java.lang.Object::<init> (1 bytes) 40 6 3 java.lang.String::isLatin1 (19 bytes) 40 7 3 java.lang.String::hashCode (49 bytes) 41 8 3 java.lang.String::coder (15 bytes) 41 9 3 java.lang.Math::floorMod (10 bytes) 41 10 3 java.lang.Math::floorDiv (22 bytes) 41 11 3 java.util.ImmutableCollections$SetN::probe (56 bytes) 42 12 3 java.lang.String::equals (65 bytes) 42 13 3 java.lang.StringLatin1::equals (36 bytes) 42 14 3 java.util.ImmutableCollections$SetN::hashCode (46 bytes) 43 15 3 java.util.Objects::equals (23 bytes) 43 16 3 java.util.ImmutableCollections::emptySet (4 bytes) 43 17 3 java.util.Set::of (4 bytes) 43 18 3 java.lang.module.ModuleDescriptor$Exports::<init> (20 bytes) 43 20 4 java.lang.StringLatin1::hashCode (42 bytes) : 70 89 3 jit.Fib::fib (27 bytes) 71 90 4 jit.Fib::fib (27 bytes) 72 89 3 jit.Fib::fib (27 bytes) made not entrant Ұ౓ΫϥΠΞϯτίϯύΠϧ ʢ-FWFMʣ͞Εͨޙɺαʔόʔί ϯύΠϧ͞Ε௚ͨ͠ʢ-FWFMʣ ΫϥΠΞϯτίϯύΠϧΛܦͯαʔ όʔίϯύΠϧ͞Ε͕ͨɺԿΒ͔ͷ ཧ༝Ͱ-ʹϑΥʔϧόοΫ͞Εͨ
  13. +7.+*5$PNQJMFS $MJFOU$PNQJMFͷόΠφϦ private static int fib(int); descriptor: (I)I flags: (0x000a)

    ACC_PRIVATE, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: iload_0 1: ifgt 6 4: iconst_0 5: ireturn 6: iload_0 7: iconst_1 8: if_icmpne 13 11: iconst_1 12: ireturn 13: iload_0 14: iconst_1 15: isub 16: invokestatic #5 // Method fib:(I)I 19: iload_0 20: iconst_2 21: isub 22: invokestatic #5 // Method fib:(I)I 25: iadd 26: ireturn 'JCKWN fi CϝιουͷΈൈਮ 'JC fi CDMJFOUQSJOU 0x000000011da82860: mov %eax,-0x14000(%rsp) 0x000000011da82867: push %rbp 0x000000011da82868: sub $0x60,%rsp 0x000000011da8286c: movabs $0x10b2cf5c0,%rdi 0x000000011da82876: mov 0x18(%rdi),%ebx 0x000000011da82879: add $0x8,%ebx 0x000000011da8287c: mov %ebx,0x18(%rdi) 0x000000011da8287f: and $0x3ff8,%ebx 0x000000011da82885: cmp $0x0,%ebx 0x000000011da82888: je 0x000000011da829af ;*iload_0 {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@0 (line 10) 0x000000011da8288e: cmp $0x0,%esi 0x000000011da82891: jle 0x000000011da8299a ;*ifgt {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@1 (line 10) 0x000000011da82897: cmp $0x1,%esi 0x000000011da8289a: je 0x000000011da82985 ;*if_icmpne {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@8 (line 12) 0x000000011da828a0: mov %rsi,%rdi 0x000000011da828a3: dec %edi 0x000000011da828a5: cmp $0x0,%edi 0x000000011da828a8: jg 0x000000011da828b8 ;*ifgt {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@1 (line 10) ; - jit.Fib::fib@16 (line 15) : 0x000000011da829af: movabs $0x10b2cf418,%r10 ; {metadata({method} {0x000000010b2cf418} 'fib' '(I)I' in 'jit/Fib')} 0x000000011da829b9: mov %r10,0x8(%rsp) 0x000000011da829be: movq $0xffffffffffffffff,(%rsp) 0x000000011da829c6: callq 0x000000011cfba400 ; ImmutableOopMap{} ;*synchronization entry ; - jit.Fib::fib@-1 (line 10) ; {runtime_call counter_overflow Runtime1 stub} ❯ java -XX:TieredStopAtLevel=2 \ -XX:+UnlockDiagnosticVMOptions \ '-XX:CompileCommand=print,*Fib.fib' \ jit.Fib 48 > ./jit/Fib.client.PrintAssembly
  14. +7.+*5$PNQJMFS $MJFOU$PNQJMFͷόΠφϦ private static int fib(int); descriptor: (I)I flags: (0x000a)

    ACC_PRIVATE, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: iload_0 1: ifgt 6 4: iconst_0 5: ireturn 6: iload_0 7: iconst_1 8: if_icmpne 13 11: iconst_1 12: ireturn 13: iload_0 14: iconst_1 15: isub 16: invokestatic #5 // Method fib:(I)I 19: iload_0 20: iconst_2 21: isub 22: invokestatic #5 // Method fib:(I)I 25: iadd 26: ireturn 'JCKWN fi CϝιουͷΈൈਮ 0x000000011da82860: mov %eax,-0x14000(%rsp) 0x000000011da82867: push %rbp 0x000000011da82868: sub $0x60,%rsp 0x000000011da8286c: movabs $0x10b2cf5c0,%rdi 0x000000011da82876: mov 0x18(%rdi),%ebx 0x000000011da82879: add $0x8,%ebx 0x000000011da8287c: mov %ebx,0x18(%rdi) 0x000000011da8287f: and $0x3ff8,%ebx 0x000000011da82885: cmp $0x0,%ebx 0x000000011da82888: je 0x000000011da829af ;*iload_0 {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@0 (line 10) 0x000000011da8288e: cmp $0x0,%esi 0x000000011da82891: jle 0x000000011da8299a ;*ifgt {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@1 (line 10) 0x000000011da82897: cmp $0x1,%esi 0x000000011da8289a: je 0x000000011da82985 ;*if_icmpne {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@8 (line 12) 0x000000011da828a0: mov %rsi,%rdi 0x000000011da828a3: dec %edi 0x000000011da828a5: cmp $0x0,%edi 0x000000011da828a8: jg 0x000000011da828b8 ;*ifgt {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@1 (line 10) ; - jit.Fib::fib@16 (line 15) : 0x000000011da829af: movabs $0x10b2cf418,%r10 ; {metadata({method} {0x000000010b2cf418} 'fib' '(I)I' in 'jit/Fib')} 0x000000011da829b9: mov %r10,0x8(%rsp) 0x000000011da829be: movq $0xffffffffffffffff,(%rsp) 0x000000011da829c6: callq 0x000000011cfba400 ; ImmutableOopMap{} ;*synchronization entry ; - jit.Fib::fib@-1 (line 10) ; {runtime_call counter_overflow Runtime1 stub} 'JC fi CDMJFOUQSJOU ͥΜͥΜΘ͔Βͳ͍ʂʂʂʂ ❯ java -XX:TieredStopAtLevel=2 \ -XX:+UnlockDiagnosticVMOptions \ '-XX:CompileCommand=print,*Fib.fib' \ jit.Fib 48 > ./jit/Fib.client.PrintAssembly
  15. +7.+*5$PNQJMFS 4FSWFS$PNQJMFͷόΠφϦ private static int fib(int); descriptor: (I)I flags: (0x000a)

    ACC_PRIVATE, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: iload_0 1: ifgt 6 4: iconst_0 5: ireturn 6: iload_0 7: iconst_1 8: if_icmpne 13 11: iconst_1 12: ireturn 13: iload_0 14: iconst_1 15: isub 16: invokestatic #5 // Method fib:(I)I 19: iload_0 20: iconst_2 21: isub 22: invokestatic #5 // Method fib:(I)I 25: iadd 26: ireturn 'JCKWN fi CϝιουͷΈൈਮ 'JC fi CTFSWFSQSJOU : 0x0000000115519ead: jmp 0x0000000115519e8f ;*invokestatic fib {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@16 (line 15) ; - jit.Fib::fib@16 (line 15) 0x0000000115519eaf: mov %rax,%rsi 0x0000000115519eb2: jmp 0x0000000115519ec1 ;*invokestatic fib {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@22 (line 15) ; - jit.Fib::fib@16 (line 15) 0x0000000115519eb4: mov %rax,%rsi 0x0000000115519eb7: jmp 0x0000000115519ec1 ;*invokestatic fib {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@16 (line 15) ; - jit.Fib::fib@22 (line 15) 0x0000000115519eb9: mov %rax,%rsi 0x0000000115519ebc: jmp 0x0000000115519ec1 ;*invokestatic fib {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@22 (line 15) ; - jit.Fib::fib@22 (line 15) 0x0000000115519ebe: mov %rax,%rsi ;*invokestatic fib {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@22 (line 15) ; - jit.Fib::fib@16 (line 15) 0x0000000115519ec1: add $0x20,%rsp 0x0000000115519ec5: pop %rbp 0x0000000115519ec6: jmpq 0x0000000115516500 ; {runtime_call _rethrow_Java} ❯ java -XX:-TieredCompilation \ -XX:+UnlockDiagnosticVMOptions \ '-XX:CompileCommand=print,*Fib.fib' \ jit.Fib 48 > ./jit/Fib.client.PrintAssembly
  16. +7.+*5$PNQJMFS 4FSWFS$PNQJMFͷόΠφϦ private static int fib(int); descriptor: (I)I flags: (0x000a)

    ACC_PRIVATE, ACC_STATIC Code: stack=3, locals=1, args_size=1 0: iload_0 1: ifgt 6 4: iconst_0 5: ireturn 6: iload_0 7: iconst_1 8: if_icmpne 13 11: iconst_1 12: ireturn 13: iload_0 14: iconst_1 15: isub 16: invokestatic #5 // Method fib:(I)I 19: iload_0 20: iconst_2 21: isub 22: invokestatic #5 // Method fib:(I)I 25: iadd 26: ireturn 'JCKWN fi CϝιουͷΈൈਮ 'JC fi CTFSWFSQSJOU : 0x0000000115519ead: jmp 0x0000000115519e8f ;*invokestatic fib {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@16 (line 15) ; - jit.Fib::fib@16 (line 15) 0x0000000115519eaf: mov %rax,%rsi 0x0000000115519eb2: jmp 0x0000000115519ec1 ;*invokestatic fib {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@22 (line 15) ; - jit.Fib::fib@16 (line 15) 0x0000000115519eb4: mov %rax,%rsi 0x0000000115519eb7: jmp 0x0000000115519ec1 ;*invokestatic fib {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@16 (line 15) ; - jit.Fib::fib@22 (line 15) 0x0000000115519eb9: mov %rax,%rsi 0x0000000115519ebc: jmp 0x0000000115519ec1 ;*invokestatic fib {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@22 (line 15) ; - jit.Fib::fib@22 (line 15) 0x0000000115519ebe: mov %rax,%rsi ;*invokestatic fib {reexecute=0 rethrow=0 return_oop=0} ; - jit.Fib::fib@22 (line 15) ; - jit.Fib::fib@16 (line 15) 0x0000000115519ec1: add $0x20,%rsp 0x0000000115519ec5: pop %rbp 0x0000000115519ec6: jmpq 0x0000000115516500 ; {runtime_call _rethrow_Java} NFUIPEDBMM͕DBMMRͯ͠ͳ͍ɻ *OMJOFԽ͞Ε͍ͯΔʜͷ͔ʁʁ ❯ java -XX:-TieredCompilation \ -XX:+UnlockDiagnosticVMOptions \ '-XX:CompileCommand=print,*Fib.fib' \ jit.Fib 48 > ./jit/Fib.client.PrintAssembly
  17. (PJOH%FFQFSʜ )PXUP6TF+*58BUDI # download and build, launch ❯ git clone

    [email protected]:AdoptOpenJDK/jitwatch.git ❯ cd jitwatch/ ❯ ./gradlew clean build run # log compilation ❯ java \ -XX:+UnlockDiagnosticVMOptions \ -XX:+TraceClassLoading \ -XX:+LogCompilation \ -XX:+PrintAssembly \ -XX:+DebugNonSafepoints \ jit.Fib 48 $PO fi HͰର৅ͷTSDDMBTTΛࢦఆ Ͱग़ྗ͞ΕΔIPUTQPU@QJEYYYYMPHΛ0QFO
  18. +*58BUDI $PNQJMFS5ISFBE"DUJWJUZ  2VFVFʹ௥Ճ͞Ε͔ͯΒɺ&NNJU͞ΕΔ·ͰͷλΠϜϥά  ͔͔ͬͨ࣌ؒ  #ZUFDPEF4J[F ɾίϯύΠϧର৅ʹͳͬͨλΠϛϯάͰ 2VFVFʹ௥Ճ͞Εɺ%FRVFVF͞ΕͯίϯύΠ

    ϧ͕׬ྃͨ࣌͠఺Ͱ&NNJU͞ΕΔ ɾଟ͘ͷ৔߹$͸NTҎԼɺ$͸NTΦʔμʔ ʹ+*5ίϯύΠϧ͸ΞϓϦέʔγϣϯʹӨڹΛ ٴ΅͢ఔ౓ͷ$16࣌ؒΛ࢖͏ ɾͨͩ͠+*5ίϯύΠϥ͸ΞϓϦέʔγϣϯε Ϩουͱ͸ผͷεϨουΛ࢖͏ͨΊɺ࣮ߦ࣌ ؒͦͷ΋ͷ΁ͷӨڹ͸େ͖͘ͳ͍
  19. 5JQT8BSNVQCZ%FFQ1JOH  ݟ͖ͯͨͱ͓Γɺ+*5ίϯύΠϧ͸͕͔͔ͦͦ࣌ؒ͜͜Δ  NTΦʔμʔ  αʔόʔΞϓϦέʔγϣϯ͸ΦϯϥΠϯʹ౤ೖ͢ΔલʹɺΤϯυϙΠϯτΛԿ ౓͔ୟ͍ͯ΍Δ͜ͱͰ౤ೖ࣌ͷੑೳྼԽΛܰݮͰ͖Δ  ଞʹ΋$MBTT-PBE΍*OWPLF%ZOBNJD౳ɺॳճʹ͕͔͔࣌ؒΔέʔε͸ଟ͍

     ͨͩ͠ɺ4FSWFS$PNQJMFͷͨΊͷΩϡʔ౤ೖᮢ஋͸σϑΥϧτͰ ճ  ͦΕͰ΋$MJFOU$PNQJMFSʹΑΔ࠷దԽ͸ظ଴Ͱ͖Δ  99$PNQJMF5ISFTIPMEͰࢦఆՄೳ͕ͩɺখ͗͘͢͞͠Δͱ)PU4QPUͷࢫຯ ͕ͳ͘ͳΔ  ίϯύΠϧࣗମʹ΋ίετ͕͔͔ΔࣄΛ๨Εͣʹ
  20. 5JQT#JOBSZTJ[F +7.+*5DPNQJMFSPWFSWJFX  +*5$PNQJMFSͷ࠷దԽ͸਺ଟ͍͕ɺॏཁͳҰͭʹΠϯϥΠϯ Խ͕͋Δ  *OWPLF999ʹΑΔϝιου࣮ߦ͸جຊతʹίετ͕ߴ͍  Ϋϥε֊૚Λ௥ͬͯϝιουΛಛఆ͠ɺ'SBNFΛ৽ ͨʹ࡞੒ͯ͠0QFSBOE4UBDLͱ-PDBM7BSΛ४උ͢Δ

     ͜ΕΛආ͚ΔͨΊɺݺͼग़͞ΕΔϝιουΛ֘౰Օॴʹ ల։ͯ͠͠·͏ͷ͕ΠϯϥΠϯԽ  99 6OMPDL%JBHOPTUJD7.0QUJPOT99 1SJOU*OMJOJOHͰ *OMJOFԽ͞ΕͨϝιουͷৄࡉΛ֬ೝͰ͖Δ  ΠϯϥΠϯԽ͞ΕΔͨΊͷ৚݅ͱͯ͠ɺόΠφϦαΠζʹ্ ݶ͕ઃ͚ΒΕ͍ͯΔ
  21. 5JQT#JOBSZTJ[F  ΠϯϥΠϯԽͰ͖ΔϝιουॲཧͷόΠφϦαΠζʹ͸੍ݶ͕͋Δ  .BY*OMJOF4J[F͸.JO*OMJOJOH5ISFTIPME %FQSFDBUFE!KBWB Λ௒͑ͳ͍ϝιουͷ੍ݶ  'SFR*OMJOF4J[F͸.JO*OMJOJOH5ISFTIPMEΛ௒͑Δճ਺࣮ߦ͞Εͨ.FUIPEʹదԠ͞ΕΔ 

    ͜ͷαΠζΛ௒͑Δϝιου͸ɺ.JO*OMJOJOH5ISFTIPMEΛ௒͑ͯ΋ΠϯϥΠϯԽ͞Εͳ͍ IPUNFUIPEUPPCJH   )PU4QPU+*5JOMJOJOHTUSBUFHZUPQEPXOPSEPXOUPQ  ͸JOTUSVDUJPOͷαΠζͳͷͰɺߦ਺ʹ͢Δͱߦະຬ͘Β͍  ฏۉCZUFJOTUSVDUJPO JOTUSVDUJPOMJOFͱԾఆͯ͠dMJOFT  େ͖͍ϝιου͸ύϑΥʔϚϯεͷ؍఺͔Β΋Ϋι ཁ͢Δʹ௕͍ϝιου͸Ϋι 99.BY*OMJOF4J[FTJ[F *OUFHFSTQFDJGZJOHNBYJNVNOVNCFSPGCZUFDPEF JOTUSVDUJPOTJOBNFUIPEXIJDIHFUTJOMJOFE EFGBVMU 99'SFR*OMJOF4J[FTJ[F *OUFHFSTQFDJGZJOHNBYJNVNOVNCFSPGCZUFDPEF JOTUSVDUJPOTJOBGSFRVFOUMZFYFDVUFENFUIPE XIJDIHFUTJOMJOFE EFGBVMU %FQFOETPO&OW PO*OUFM.BD Š+BWB)PU4QPU&RVJWBMFOUTPG&YBDU7.'MBHT
  22. 5JQT#JOBSZTJ[F  +*58BUDIʹ෇ਵ͢Δɺ+*5ίϯύΠϥͷ؍఺͔ΒKBSϑΝΠϧͷதͷϚζ͍࣮૷Λநग़ͯ͘͠Ε Δπʔϧ  NBY.FUIPE4J[FΦϓγϣϯͰΠϯετϥΫγϣϯ͕UISFBTIPMEҎ্ͷϝιουΛநग़Ͱ͖Δ  (SBEMFCVJMEͰ͸ͦͷ··ಈ͔ͳ͍ͷͰNWOͰϏϧυ͢Δ͔εΫϦϓτΛॻ͖׵͑Δඞཁ ͋Γ ཁ͢Δʹ௕͍ϝιου͸Ϋι

    +*58BUDIFS+BS4DBO ❯ cd jitwatch/script ❯ ./jarScan.sh --mode=maxMethodSize --limit=325 ./core/build/libs/core.jar "org.adoptopenjdk.jitwatch.model.bytecode","BytecodeAnnotationBuilder","buildParseTagAnnotations","org.adoptopenjdk.jitwatch.mode l.Tag,org.adoptopenjdk.jitwatch.model.bytecode.BytecodeAnnotations,org.adoptopenjdk.jitwatch.model.IParseDictionary",1314 “org.adoptopenjdk.jitwatch.hotthrow","HotThrowFinder","visitTag","org.adoptopenjdk.jitwatch.model.Tag,org.adoptopenjdk.jitwatch.m odel.IParseDictionary",700 :
  23. 5JQT1PMZNPSQIJTN +*58BUDIFS4BOE#PY public class PolymorphismTest { public interface Coin {

    void deposit();} public static int moneyBox = 0; public class Nickel implements Coin { public void deposit() { moneyBox += 5; }} public class Dime implements Coin { public void deposit() { moneyBox += 10; }} public class Quarter implements Coin { public void deposit() { moneyBox += 25; }} public PolymorphismTest() { Coin nickel = new Nickel(); Coin dime = new Dime(); Coin quarter = new Quarter(); Coin coin = null; // change the variable maxImplementations to control the inlining behaviour // 2 = bimorphic dispatch - the method call will be inlined // 3 = megamorphic dispatch - the method call will not be inlined final int maxImplementations = 2; for (int i = 0; i < 1_000_000; i++) { switch (i % maxImplementations) { case 0: coin = nickel; break; case 1: coin = dime; break; case 2: coin = quarter; break; } coin.deposit(); } System.out.println("moneyBox:" + moneyBox); } public static void main(String[] args) { new PolymorphismTest(); } } 1PMZNPSQIJTN5FTUKBWB  $PJO*OUFSGBDFʹͭͷ࣮૷Λ ΋ͭ؆қͳςετΫϥε  NBY*NQMFNFOUBUJPOTͰར༻ ͢Δ࣮૷ΫϥεΛ੍ޚ͍ͯ͠Δ
  24. 5JQT1PMZNPSQIJTN NBY*NQMFNFOUBUJPOT 0x000000011b27197c: mov 0xb8(%rsi),%r9d ;*getstatic moneyBox {reexecute=0 rethrow=0 return_oop=0}

    ; - PolymorphismTest$Nickel::deposit@0 (line 5) ; - PolymorphismTest::<init>@93 (line 32) 0x000000011b271983: mov %r9d,%r11d 0x000000011b271986: sub %r10d,%r11d 0x000000011b271989: add $0x5,%r9d 0x000000011b27198d: mov %r9d,0xb8(%rsi) ;*iload {reexecute=0 rethrow=0 return_oop=0} ; - PolymorphismTest::<init>@40 (line 22) 0x000000011b271994: add %ebx,%edi 0x000000011b271996: add %r11d,%edi 0x000000011b271999: mov %edi,%r9d 0x000000011b27199c: add $0xa,%r9d ;*iadd {reexecute=0 rethrow=0 return_oop=0} ; - PolymorphismTest$Nickel::deposit@4 (line 5)  - $ ͰϝιουࣗମɺϝιουίʔϧͲͪΒ΋ ΠϯϥΠϯԽ͞Εͨ
  25. 5JQT1PMZNPSQIJTN NBY*NQMFNFOUBUJPOT 0x000000011d7fd837: cmp %rsi,%rcx 0x000000011d7fd83a: jne 0x000000011d7fd872 ;*invokeinterface deposit

    {reexecute=0 rethrow=0 return_oop=0} ; - PolymorphismTest::<init>@93 (line 32) 0x000000011d7fd83c: add $0x5,%r11d : 0x000000011d7fd872: cmp %rax,%rcx 0x000000011d7fd875: jne 0x000000011d7fda1b ;*invokeinterface deposit {reexecute=0 rethrow=0 return_oop=0} ; - PolymorphismTest::<init>@93 (line 32) 0x000000011d7fd87b: add $0xa,%r11d  ΠϯϥΠϯԽ͞Ε͍ͯΔ  ࣮૷͝ͱʹ࣮ߦઌ੍͕ޚ͞Ε͍ͯͦ͏
  26. 5JQT1PMZNPSQIJTN NBY*NQMFNFOUBUJPOT  %FQPTJUϝιουͷத਎͸ΠϯϥΠϯԽ ͞Ε͕ͨɺJOWPLFJOUFSGBDF͸ΠϯϥΠ ϯԽ͞Εͳ͍ʢDBMMRʹΑΔؔ਺ίʔϧʣ 0x0000000121a7180f: mov 0x18(%rsp),%rsi 0x0000000121a71814:

    nop 0x0000000121a71815: movabs $0xffffffffffffffff,%rax 0x0000000121a7181f: callq 0x0000000119ef1c00 ; ImmutableOopMap{[0]=Oop [8]=Oop [16]=Oop [24]=Oop } ;*invokeinterface deposit {reexecute=0 rethrow=0 return_oop=0} ; - PolymorphismTest::<init>@93 (line 32) ; {virtual_call} 0x0000000121a71824: inc %ebp ;*iinc {reexecute=0 rethrow=0 return_oop=0}
  27. 4VN6Q  8IBUJT+*5$PNQJMFS  w %PCJOBSZMFWFMPQUJNJ[BUJPO $PNQJMF +VTU*O5JNF w )PU4QPU7.

     %JWFJOUP+7.+*5$PNQJMFS w $MJFOU4FSWFS$PNQJMFS w 5JFSFE$PNQJMBUJPO w +*58BUDIUPEFFQEJWF  1FSGPSNBODF5JQT w %FFQQJOHXBSNVQ w 5BLF$BSFPG#JOBSZ4J[F w 5BLF$BSFPG1PMZNPSQIJTN
  28. 3FGFSFODFT w +*5ίϯύΠϥͷ࣮ࡍͷಈ࡞+BWB.BHB[JOF w *OUSPEVDUJPOUP+*5$PNQJMBUJPOJO+BWB)PU4QPU7. w 6OEFSTUBOEJOH+BWB+*5$PNQJMBUJPOXJUI+*58BUDI 1BSU w +*58BUDIʹΑΔ+BWB+*5ίϯύΠϧͷௐࠪ+BWB.BHB[JOF

    w +7.+*5DPNQJMFSPWFSWJFX w 0QFO+%,1SJOU"TTFNCMZ w +*58BUDI w )PU4QPUQSP fi MJOHXJUI+*58BUDI w +BWB)PU4QPU&RVJWBMFOUTPG&YBDU7.'MBHT w 3FBEJOHBTTFNCMZGSPNUIF+7. w 1SJOU"TTFNCMZPVUQVUFYQMBJOFE