JITコンパイラーは最適化をクールではなく、非常にクールに

最近、Lucas Eder 、1つの要素からリストの不要なクロールを削除するために、Java JITコンパイラーがそのようなコードを最適化できるかどうかに関するブログに興味を持ちました







// ...    "",      
for (Object object : Collections.singletonList("abc")) {
    doSomethingWith(object);
}
      
      





: JIT . HotSpot JVM 64 bit . , :







static int testIterator(List<String> list) {
    int sum = 0;
    for (String s : list) {
        sum += s.length();
    }
    return sum;
}
      
      





Java- , :







static int testIterator(List<String> list) {
    int sum = 0;
    Iterator<String> it = list.iterator();
    while(it.hasNext()) {
        String s = it.next();
        sum += s.length();
    }
    return sum;
}
      
      





, list



JIT- iterator()



, hasNext()



next()



, , , . , , singletonList



? main()



:







public class Test {
    static int res = 0;

    public static void main(String[] args) {
        for (int i = 0; i < 100000; i++) {
            res += testIterator(Collections.singletonList("x"));
        }
        System.out.println(res);
    }
}
      
      





testIterator



, JIT- C2. , HotSpot JIT-: C1 () C2 (). 64- Java 8 . C1 ( , ). , ( ""). , , , . . JVM , list



. , 100% Collections$SingletonList ( singletonList



).







, C2, . C2 , SingletonList



, . , iterator()



singletonIterator(). , , , hasNext



, , , NoSuchElementException



. C2 ?







, JIT- . hsdis. JITWatch JMH- -perfasm



. , :







$ java -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintAssembly Test >output.txt
      
      





: . , , testIterator



. C2 Intel x64 4 :







,
  # {method} {0x0000000055120518} 'testIterator' '(Ljava/util/List;)I' in 'Test'
  # parm0:    rdx:rdx   = 'java/util/List'
  #           [sp+0x20]  (sp of caller)
  0x00000000028e7560: mov    %eax,-0x6000(%rsp)
  0x00000000028e7567: push   %rbp
  0x00000000028e7568: sub    $0x10,%rsp         ;*synchronization entry
                                                ; - Test::testIterator@-1 (line 15)

  0x00000000028e756c: mov    0x8(%rdx),%r10d    ; implicit exception: dispatches to 0x00000000028e75bd
  0x00000000028e7570: cmp    $0x14d66a20,%r10d  ;   {metadata('java/util/Collections$SingletonList')}
  0x00000000028e7577: jne    0x00000000028e75a0  ;*synchronization entry
                                                ; - java.util.Collections::singletonIterator@-1
                                                ; - java.util.Collections$SingletonList::iterator@4
                                                ; - Test::testIterator@3 (line 16)

  0x00000000028e7579: mov    0x10(%rdx),%ebp    ;*getfield element
                                                ; - java.util.Collections$SingletonList::iterator@1
                                                ; - Test::testIterator@3 (line 16)

  0x00000000028e757c: mov    0x8(%rbp),%r11d    ; implicit exception: dispatches to 0x00000000028e75c9
  0x00000000028e7580: cmp    $0x14d216d0,%r11d  ;   {metadata('java/lang/String')}
  0x00000000028e7587: jne    0x00000000028e75b1
  0x00000000028e7589: mov    %rbp,%r10          ;*checkcast
                                                ; - Test::testIterator@24 (line 16)

  0x00000000028e758c: mov    0xc(%r10),%r10d    ;*getfield value
                                                ; - java.lang.String::length@1
                                                ; - Test::testIterator@30 (line 17)

  0x00000000028e7590: mov    0xc(%r10),%eax     ;*synchronization entry
                                                ; - Test::testIterator@-1 (line 15)
                                                ; implicit exception: dispatches to 0x00000000028e75d5
  0x00000000028e7594: add    $0x10,%rsp
  0x00000000028e7598: pop    %rbp
  0x00000000028e7599: test   %eax,-0x27b759f(%rip)        # 0x0000000000130000
                                                ;   {poll_return}
  0x00000000028e759f: retq   
  ... //   
      
      





, — . , :







//    -     JIT- 
mov    %eax,-0x6000(%rsp)
push   %rbp
sub    $0x10,%rsp         
//       list (        rdx).
//        0x8.     list.getClass().
//        null.  ,     null,
//           .
//          NullPointerException
mov    0x8(%rdx),%r10d
//  list.getClass()    Collections$SingletonList.    
//    JVM , , JIT  ,      
cmp    $0x14d66a20,%r10d
//  list -   SingletonList,    
jne    0x00000000028e75a0
//    Collections$SingletonList.element   rbp.   64-,    
//  4   32   ,          32    ebp
mov    0x10(%rdx),%ebp
//           String ( ,  )
mov    0x8(%rbp),%r11d
cmp    $0x14d216d0,%r11d
//    -  ,      (     ClassCastException)
jne    0x00000000028e75b1
//    String.value   r10.   char[],     
mov    %rbp,%r10
mov    0xc(%r10),%r10d
//      eax,        
mov    0xc(%r10),%eax
//   
add    $0x10,%rsp
pop    %rbp
//   safe-point.    JVM      , ,   .
test   %eax,-0x27b759f(%rip)
//   
retq   
      
      





- , :







if (list.class != Collections$SingletonList) {
  goto SLOW_PATH;
}
str = ((Collections$SingletonList)list).element;
if (str.class != String) {
  goto EXCEPTIONAL_PATH;
}
return ((String)str).value.length;
      
      





? , , . ( , ). JIT- , , , , , hasNext



, , ! sum



. , . , singletonList



, - , (, , ). . null



list



( type erasure) — .







, ? , singletonList



. . , , JIT- , singletonList



. , , , . JIT : , .








All Articles